Git自学笔记
Git是目前世界上最先进的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git与SVN的区别有哪些?
① Git是分布式的,SVN不是。这是Git和其它非分布式版本控制系统(如:SVN,CVS等)最核心的区别。
② Git把内容按元数据方式存储,而SVN是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn、.cvs等的文件夹里。
③ Git分支和SVN的分支不同:分支在SVN中一点不特别,就是版本库中的另外的一个目录。
④ Git没有一个全局的版本号,而SVN有:目前为止这是跟SVN相比Git缺少的最大的一个特征。
⑤ Git的内容完整性要优于SVN:Git的内容存储使用的是SHA-1哈希算法,这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
如何安装、配置Git(以Windows操作系统为例)?
安装步骤可以上网参考其他教程,安装完成之后打开Git Bash,若弹出一个类似命令窗口的东西,则说明Git安装成功。安装完成后,还需要设置用户信息(即配置个人用户名称和电子邮件地址),命令如下:
$ git config --global user.name "example"
$ git config --global user.email example@126.com
注意:① 因为Git是分布式版本控制系统,所以需要填写用户名和邮箱作为一个标识。
② git config --global 参数,有了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然你也可以对某个仓库指定的不同的用户名称和电子邮件地址。
几个基础命令
要查看安装Git的版本信息,可以使用 git --version命令,如下:
$ git --version
要查看已有的配置信息,可以使用 git config --list 命令,如下:
$ git config --list
要查看当前所在目录,可以使用pwd命令,如下:
$ pwd
创建版本库
首先使用cd命令进入目标文件夹,如进入D:\Development Tools\Git的命令如下:
$ cd d:
$ cd development" "tools
$ cd git
注意:由于Development和Tools之间有空格,所以要用" "来表示空格。
通过命令git init把某个目录变成Git可以管理的仓库,命令如下:
$ mkdir test_repository // 在当前目录下创建test_repository目录
$ cd test_repository
$ git init // 使用当前目录(即test_repository)作为Git仓库。或者使用指定目录(即test_repository)作为Git仓库,命令为:$ git init test_repository。
注意:此时test_repository目录下就多一个.git的目录,这个目录是Git来跟踪管理版本的,千万不要改目录里的文件,否则会破坏Git仓库。
从现在开始,除非另有说明,否则我们将默认您在Git仓库根目录下。
添加、提交文件到版本库
【添加新文件】我们有一个仓库,但什么也没有,可以使用add命令把文件添加到暂存区中去 ,命令如下:
$ git add filename
可以使用add... 继续添加任务文件。
如果需要提交目录A下的所有内容,可以这样做:
$ git add .
【提交版本】现在我们已经添加了这些文件,我们希望它们能够真正被保存在Git仓库。为此,我们将它们提交到仓库。
$ git commit -m "文件初始提交"
如果您不使用-m,会出现编辑器来让你写自己的注释信息。
当我们修改了很多文件,而不想每一个都add,想commit自动来提交本地修改,我们可以使用-a标识。
$ git commit -a -m "第一次修改提交"
git commit 命令的-a选项可将所有被修改或者已删除的且已经被git管理的文档提交到仓库中。千万注意,-a不会造成新文件被提交,只能修改。
可以通过git status命令查看是否还有文件未提交,例如:
$ git status
理解工作区与暂存区的区别?
工作区:就是在电脑上看到的目录,比如目录下test_repository里的文件(.git隐藏目录版本库除外)或以后需要新建的目录\文件等都属于工作区范畴。
版本库(Repository):工作区有一个隐藏目录.git,这个不属于工作区而是版本库。版本库里存了很多东西,最重要的就是stage(暂存区),还有Git为我们自动创建的第一个分支master以及指向master的一个指针HEAD。
前面说过使用Git提交文件到版本库只需两步:
第一步:使用git add把文件添加进去,实际上就是把文件添加到暂存区。
第二步:使用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支上。
查看历史、回退版本
假如要看readme.txt文件中改了什么内容,可以使用如下命令:
$ git diff readme.txt
假如想查看历史记录,可以使用命令 git log命令:
$ git log
注意:git log命令显示从最近到最远的日志。如果嫌上面的方法显示的信息太多,可以使用命令 git log --pretty=oneline命令:
$ git log --pretty=oneline
假如想使用版本回退操作,如:把当前的版本回退到上一个版本,可以使用2种命令,第一种是:
$ git reset --hard HEAD^
如果要回退到上上个版本,命令如下:
$ git reset --hard HEAD^^
……以此类推。那如果要回退到前100个版本的话,使用上面的方法肯定不方便,此时就可以使用下面的命令:
$ git reset --hard HEAD~100
即可。
若回退之后又想退回到最新版本,可通过版本号回退,命令如下:
$ git reset --hard 版本号
如果已经关掉过一次命令行或者并不知道最新内容的版本号,可以通过如下命令获取版本号:
$ git reflog
找到版本号之后就可以通过$ git reset --hard 版本号 退回到最新版本了。
撤销修改操作
通过cat命令查看某个文件中的详细内容,例如:
$ cat readme.txt
在未提交之前,若发现添加的文件内容有误,得马上恢复到以前的版本,可以有如下几种方法:
第一:如果知道应该删掉哪些内容,直接手动更改文件然后add到暂存区,最后commit即可。
第二:可以直接恢复到上一个版本,使用 git reset --hard HEAD^命令即可。
如果不想使用上面2种方法,也可以直接使用撤销命令。首先,在做撤销之前,可以先用git status查看下当前的状态。此时Git会告诉你,git checkout -- file可以丢弃工作区的修改,如下命令:
$ git checkout -- readme.txt
git checkout --readme.tx命令的意思:把readme.txt文件在工作区做的修改全部撤销,此时有2种情况,如下:① readme.txt自动修改后,还没有放到暂存区,使用 撤销修改就回到和版本库一模一样的状态。
② readme.txt已经放入暂存区,接着又作了修改,撤销修改就回到添加暂存区后的状态。
对于第②种情况,可以做试验看看。
注意:git checkout -- readme.txt命令中的“ -- ”,如果没有“ -- ”的话该命令就变成创建分支了。
删除文件操作
一般情况下,可以直接在工作区的文件目录中把文件删掉或使用rm命令($ git rm readme.txt),如果想彻底从版本库中删掉此文件可以再执行commit命令。
在没有执行commit命令之前,如果想在版本库中恢复此文件,可以使用如下命令:
$ git checkout -- readme.txt
远程仓库的使用
在此之前,需要先注册GitHub账号,由于本地的Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以需要设置一下:① 创建SSH Key。在用户主目录下(一般是C:\Users\Administrator)看是否有.ssh目录,如果有,再看这个目录下是否有id_rsa和id_rsa.pub两个文件,如果有就直接跳过。如果没有的话,打开命令行,输入命令:ssh-keygen -t rsa –C example@126.com”即可。注意:id_rsa是私钥,不能泄露给别人,id_rsa.pub是公钥,可以放心告诉任何人。② 登录GitHub,打开”settings”中的SSH Keys页面,然后点击“Add SSH Key”,填上任意title,在Key文本框里黏贴id_rsa.pub文件的内容,点击Add Key即可。
假如我们已经在本地创建了一个Git仓库,又想在GitHub创建一个Git仓库,并且希望这两个仓库进行远程同步,这样GitHub的仓库既可以作为备份,又可以让其他人通过该仓库来协作。
首先,登录GitHub上,然后在右上角找到“Create a new repository”创建一个新的仓库。在Repository name填入test_repository,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库。目前,GitHub上的这个test_repository仓库是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后把本地仓库的内容推送到GitHub仓库。
现在,我们根据GitHub的提示,在本地的test_repository仓库下运行命令:
$ git remote add origin https://github.com/example/test_repository.git
再使用git push命令把本地Git仓库里的内容推送到远程Git仓库,如下:
$ git push -u origin master
由于远程Git仓库还是空的,所以第一次推送master分支时加上了–u参数,Git不但会把本地的master分支内容推送到远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样了。
此后,只要本地作了提交,就可以通过如下命令:
$ git push origin master
就能把本地master分支的最新修改推送到GitHub上了,现在就拥有真正的分布式版本库了。
如何从远程库克隆
如果想把远程Git仓库克隆到本地来,使用如下命令即可:
$ git clone https://github.com/example/test_repository1.git
创建、切换、合并分支
在版本回退中我们已经知道:每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。现在创建一个dev分支并切换到dev分支上:
$ git checkout -b dev
注意:git checkout命令加上–b参数表示创建并切换,相当于如下2条命令:
$ git branch dev // 创建新的分支,名称为dev
$ git checkout dev // 切换到指定分支(此处为dev)上
使用git branch命令查看分支时会列出所有分支,但当前分支前面会多一个*,命令如下:
$ git branch
此外,还可以把dev分支上的内容合并到分支master上,在master分支上使用命令 git merge dev即可:
$ git merge dev
注意:git merge命令用于合并指定分支到当前分支上,合并后再查看readme.txt内容,它就和dev分支最新提交的是完全一样的。
合并完成后,接着就可以删除dev分支了,命令如下:
$ git branch -d dev
创建、切换、合并分支命令总结
查看分支:$ git branch 创建分支:$ git branch name 切换分支:$ git checkout name 创建+切换分支:$ git checkout –b name 合并某分支到当前分支:$ git merge name 删除分支:$ git branch –d name
如何解决冲突
先新建一个新分支test,在readme.txt中添加一行内容“第三次:test分支”,然后提交,命令如下:
$ git checkout -b test $ cat readme.txt // 添加内容前 $ cat readme.txt // 添加内容后 $ git add readme.txt $ git commit -m "使用test分支"
同样,切换到master分支上,也在readme.txt中内容“第三次:使用master分支”,然后提交,命令如下:
$ git checkout master $ cat readme.txt // 添加内容前 $ cat readme.txt // 添加内容后 $ git add readme.txt $ git commit -m "使用master分支"
接下来在master分支上合并test分支,命令如下:
$ git merge test // 产生冲突 $ git status // 查看状态 $ cat readme.txt // 查看readme.txt文件中的冲突内容
注意:Git用<<<<<<<、=======、>>>>>>>标记出不同分支的内容。其中<<<HEAD是指主分支修改的内容,>>>>>test是指test分支上修改的内容。此时可以修改下readme.txt内容后保存:
$ cat readme.txt // 查看readme.txt文件中的内容,修改成和master分支上的内容一样
在执行添加、提交命令:
$ git add readme.txt $ git commit -m "解决冲突"
如果想查看分支合并的情况,需要使用命令git log,如下:
$ git log
分支管理策略
通常,合并分支时git一般使用”Fast forward”模式,在这种模式下,删除分支后会丢掉分支信息,现在使用带参数–no-ff来禁用”Fast forward”模式。试验如下:① 创建一个dev分支:
$ git checkout -b dev
② 修改readme.txt内容③ 添加到暂存区:
$ git add readme.txt $ git commit -m "提交"
④ 切换回主分支(master):
$ git checkout master
⑤ 合并dev分支(使用命令git merge –no-ff -m “注释” dev):
$ git merge --no-ff -m "merge with no-ff" dev
⑥ 查看历史记录:
$ git log --graph --pretty=oneline --abbrev-commit
分支策略:首先master主分支应该是非常稳定的,用来发布新版本,一般情况下不允许在上面干活,一般情况下在新建的dev分支上干活,干完后,比如上要发布或dev分支代码稳定后才可以合并到主分支master上。
bug分支
在开发中会经常碰到bug,有了bug就需要修复。在Git中,分支是很强大的,每个bug都可以通过一个临时分支来修复,修复完成后再合并分支,最后将临时的分支删除掉。假如在开发中遇到一个404的bug就可以创建一个404分支来修复它,但是当前的dev分支上的工作还没有提交。并不是我不想提交,而是工作进行到一半还无法提交,比如这个分支bug要2天完成,但是404的bug需要5个小时内完成。怎么办?Git提供了一个stash功能,可以把当前工作现场”隐藏起来”,等以后恢复现场后继续工作:
$ git stash
现在可以通过创建issue-404分支来修复bug。首先要确定在那个分支上修复bug,比如现在是在主分支master上修复的,就要在master分支上创建一个临时分支:
$ git checkout -b issue-404
修复完成后切换到master分支上,并完成合并,最后删除issue-404分支:
$ git checkout master $ git merge --no-ff -m "修复404bug" isuue-404 $ git branch -d issue-404
现在又可以回到dev分支上干活了:
$ git checkout dev
工作区是干净的,此时可以使用命令git stash list来查看:
$ git stash list
工作现场还在,Git把stash内容存在某个地方了,需要恢复一下,可以使用如下2个方法:① 使用git stash apply,恢复后stash内容并不删除,需要使用git stash drop命令来删除:
$ git stash drop
② 使用git stash pop,恢复的同时把stash内容也删除了:
$ git stash pop
多人协作
当你从远程库克隆时候,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且远程库的默认名称是origin。① 查看远程库的信息
$ git remote
② 查看远程库的详细信息
$ git remote –v
推送分支
推送分支就是把该分支上所有本地文件提交到远程库中,推送时要指定本地分支,这样Git就会把该分支推送到远程库对应的远程分支上,如:
$ git push origin master
假设现在GitHub上readme.txt内容为:第一次:12345678910而本地readme.txt内容为:第一次:12345678910第二次:147258369现在想把本地更新的readme.txt推送到远程库中:
$ git add readme.txt $ git commit -m "推送分支" $ git push origin master
如果现在要推送到其他分支(如:dev分支)上:
$ git push origin dev
一般情况下,那些分支要推送呢?master分支是主分支,因此要时刻与远程同步。一些修复bug分支不需要推送到远程去,可以先合并到主分支上,然后把主分支master推送到远程去。
抓取分支
多人协作时,大家都会往master分支上推送自己的修改。现在另一个目录下克隆,新建一个目录名字叫test_repository2。首先要把dev分支推送到远程去:
$ git push origin dev
接着进入test_repository2目录,克隆远程库到本地来:
$ git clone https://github.com/example/test_repository.git
接下来要在dev分支上做开发,就必须把远程的origin的dev分支到本地来,使用命令创建本地dev分支:
$ git checkout –b dev origin/dev
现在就可以在dev分支上做开发了,开发完成后把dev分支推送到远程库:
$ git push origin dev
注意:不同的人修改了同一文件相同地方后推送会失败,因为推送的有冲突,解决办法很简单,先用git pull把最新的提交从origin/dev抓下来,然后在本地合并,解决冲突后再推送。根据提示先指定本地dev分支与远程origin/dev分支的链接:
$ git branch --set-upstream dev origin/dev
然后再执行:
$ git pull
如果合并有冲突,就需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,先提交,再push。因此,多人协作工作模式一般是这样的:首先,用git push origin branch-name推送自己的修改。如果推送失败,则因为远程分支比你本地更新早,需要先用git pull合并。如果合并有冲突,则需要解决冲突,并在本地提交。再用git push origin branch-name推送。
附:Git基本常用命令
$ mkdir XX:创建一个空目录,XX指目录名 $ pwd:显示当前目录的路径 $ git init:把当前的目录变成可以管理的git仓库,生成隐藏.git文件 $ git add XX:把xx文件添加到暂存区去 $ git commit –m “XX”:提交文件 –m 后面的是注释 $ git status:查看仓库状态 $ git diff XX:查看XX文件修改了那些内容 $ git log:查看历史记录 $ git reset --hard HEAD^(或$ git reset --hard HEAD~):回退到上一个版本 $ git reset –hard HEAD~100:回退到100个版本 $ cat XX:查看XX文件内容 $ git reflog:查看历史记录的版本号id $ git checkout -- XX:把XX文件在工作区的修改全部撤销 $ git rm XX:删除XX文件 $ git remote add origin https://github.com/example/test_git:关联一个远程库 $ git push –u(第一次要用-u,以后不需要) origin master:把当前master分支推送到远程库 $ git clone https://github.com/example/test_git:从远程库中克隆 $ git checkout –b dev:创建dev分支,并切换到dev分支上 $ git branch:查看当前所有的分支 $ git checkout master:切换回master分支 $ git merge dev:在当前的分支上合并dev分支 $ git branch –d dev:删除dev分支 $ git branch name:创建分支 $ git stash:把当前的工作隐藏起来 等以后恢复现场后继续工作 $ git stash list:查看所有被隐藏的文件列表 $ git stash apply:恢复被隐藏的文件,但是内容不删除 $ git stash drop:删除文件 $ git stash pop:恢复文件的同时 也删除文件 $ git remote:查看远程库的信息 $ git remote –v:查看远程库的详细信息 $ git push origin master:Git会把master分支推送到远程库对应的远程分支上
问:Git Bash中如何cd进入带空格的目录?
答:如要进入名为java tools文件夹,只需:cd java" "tools即可。
问:Git Gui图形化工具中文显示乱码的解决方案?
答:在操作系统的宿主目录(通常是C:\Users\Administrator)下有一个 .gitconfig 文件,在文件最后追加
[gui] encoding = utf-8
即可。
问:使用Git命令如何删除本地仓库?
$ ls -a // 查看内部文件 $ rm -rf .git // 强删.git $ ls -a // 查看内部文件 $ cd .. // 回退 $ rm -rf test_repository // 强删文件夹