git学习笔记2
git学习笔记之二
从廖大神的git教程的分支管理开始
- 分支的创建与合并
- 首先,创建
dev
分支,然后切换到dev
分支git checkout
命令加上-b
参数表示创建并切换,相当于以下两条命令:$ git branch dev
$ git checkout dev
Switched to branch 'dev'
然后用git branch
命令查看当前分支:git branch
命令会列出所有分支,当前分支前面会标一个*号 - 然后 我们就可以在
dec
分支上正常提交,比如对readme.txt做个修改,然后提交: - 现在,
dev
分支的工作完成,可以切换回master
分支:git checkout master
Switch to branch 'master'
- 切换回
master
分支后,再查看一下readme.txt文件,刚才添加的内容不见了。因为提交是在dev
分支上,而master
分支此刻的提交点并没有变。 - 现在我们把
dev
分支的工作成果合并到master
分支上:git merge
命令用于合并制定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到是和dev
分支的最新提交是完全一样的。
注意上面的Fast-forward
信息,Git告诉我们,这次合并是”快进模式”,也就是直接把master
指向dev
当前提交,所以合并速度非常快。当然也不是每次合并都能Fast-forward
,后面会讲其他方式的合并。 - 合并完成后,就可以删除
dev
分支了:git branch -d dev
Deleted branch dev (was e4b32fb)
删除后,使用git branch
查看分支,就发现只剩下master
分支了。 - 小结
- Git鼓励大量使用分支:
- 查看分支
git branch
- 创建分支
git branch <name>
- 切换分支
git checkout <name>
- 创建+切换分支
git checkout -b <name>
- 合并某分支到当前分支
git merge <name>
- 删除分支
git branch -d <name>
- 首先,创建
- 解决冲突
- 创建并切换到新的
feature1
分支,git checkout -b feature1
Switch to a new branch 'feature1'
- 修改readme.txt的最后一行
Creating a new branch is quick AND simple.
- 在
feature1
分支上提交$ git add readme.txt
$ git commit -m "AND simple"
[feature1 0e8692f] AND simple
1 file changed, 1 insertion(+), 1 deletion(-)
- 切换到
master
分支$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
- 在
master
分支上把 readme.txt文件的最后一行改为:Creating a new branch is quick & simple.
- 在
master
分支上提交。现在,master
分支和feature1
分支各自的readme.txt都分别有新的提交。这种情况下,Git无法执行快速合并,只能吧各自的修改合并起来,但这种合并就可能会有冲突。我们合并看一下:$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
- 冲突了!GIT告诉我们 readme.txt文件存在冲突,必须手动解决冲突后再提交。
git status
也可以告诉我们冲突的文件:$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
- 我们查看readme.txt中的内容,冲突基本和SVN的类型一样,我们手动修改后,再进行添加和提交操作就OK了,最后别忘了删除
feature1
分支。 - 小结
- 当git无法自动合并分支时,就必须首先解决冲突。冲突解决后,再提交,完成合并
- 用
git log --graph
命令可以看到分支合并图。
- 创建并切换到新的
- 分支管理策略
- 通常,合并分支时,如果可能,git会用
Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。 - 如果要强制禁用
Fast forward
模式,Git就会在merge
时生成一个新的commit
,这样,从分支历史上就可以看出分支信息。 - 我们实战一下
--no-ff
方式的git merge
:
先创建并切换dev
分支:$ git checkout -b dev
Switched to a new branch 'dev'
- 修改readme.txt文件,并提交一个新的
commit
- 提价后 切换回
master
分支git checkout master
Switched to branch 'master'
- 准备合并
dev
分支,请注意--no-ff
参数,表示禁用Fast forward
:git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
- 因为本地合并要创建一个新的commit,所以加上
-m
参数,把commit描述写进去 - 合并后,我们可以用
git log
查看分支历史:$ git log --graph --pretty=oneline --abbrev-commit
- 分支策略
在实际开发中,应该按照几个基本原则进行分支管理:- 首先,
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不在此分支上干活 - 干活都在
dev
分支上,也就是说dev
分支是不稳定的,到某个时候,比如版本发布时,再把dev
分支合并到master
上,在master
分支发布新版本
- 首先,
- 小结
- Git分支十分强大,在团队开发中应该充分应用
- 合并分支时,加上
--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而Fast foward
合并就看不出来曾经做过合并- BUG分支
- 软件开发中,有bug很正常,有bug就需要修复,在GIT中,由于分支很强大,所以每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除
- 当我们需要修复一个bug时,我们很自然的想到创建一个新分支来修复它,但是当前正在
dev
分支上进行的工作只进行到一半,还没办法提交,而且BUG还需要很快修复。怎么办? - 为了解决上述问题,Git提供了一个
git stash
命令,可以把当前工作现场储藏起来,等以后恢复现场后继续工作:git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge
- 现在再用
git status
查看工作区,就是干净的(除非有没有被Git管理的文件),然后就可以放心的创建分支修复BUG了。 - 首先确定要在哪个分支上修复BUG,假设需要在
master
分支上修复,就从master
创建临时分支 - 修复BUG后,切换到
master
分支,并完成合并,最后删除issue-101
分支 - 然后切换回
dev
分支,由于我们刚才隐藏了一个文件,所以此时工作区是干净的,我们先用git stash list
命令看看,发现工作现场还在,接下来我们需要回复工作现场,有两个办法- 一是用
git stash apply
恢复,但是恢复后,stash内容并不删除,需要用git stash drop
来删除 - 另一种使用
git stash pop
,恢复的同时把stash内容也删了。
- 一是用
- 小结
- 修复BUG时,我们会通过创建新的分支进行修复,然后合并,最后删除
- 当手头工作没有完成时,先把工作现场
git stash
一下,然后修复BUG ,修复后,在git stash pop
,回到工作现场
- 通常,合并分支时,如果可能,git会用
- feature 分支
- 软件开发过程中,总会有新功能会添加进来。添加一个新功能时,肯定不能因为一下实验性质的代码,把主分支搞乱了,所以 每添加一个新功能。最好新建一个feature分支。在上面开发完毕后,合并。最后删除该feature分支
- 小结
- 开发一个新feature,最好新建一个分支
- 如果要丢弃一个没有被合并过的分支,可以通过
git branch -D <name>
强行删除
- 多人协作
- 当你从远程仓库克隆代码时,实际上Git自动把本地的
master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称室origin
,要查看远程库的信息,用git remote
或者 用git remote -v
显示更详细的信息:
上面显示了可以抓取和推送的origin
地址,如果没有推送权限,就看不到push的地址 - 推送分支,就是把该分支上的所有本地提交推送到远程库,推送时,要制定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
git push origin master
如果要推送其他分支,比如dev
,就改成git push origin dev
- 但是,并不是一定要把本地分支往远程推送,下面是是否要推送的判断准则
-
master
分支是主分支,因此要时刻与远程同步 -
dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步 - bug分支只用于在本地修复BUG,就没必要推到远程了,除非领导要看你的bug修复量
- feature分支是否推送到远程,取决于你是否和同事合作在上面开发
- 总之,在GIT中,分支完全可以在本地自己隐藏,是否推送视情况而定
-
- 抓取分支,多人协作时,大家都会往
master
和dev
分支上推送各自的修改, - 现在,模拟一个小伙伴,可以在另一目录下克隆:
- 当你的小伙伴从远程库clone时,默认情况下,只能看到本地的
master
分支 - 现在,小伙伴要在
dev
分支上开发,就必须创建远程origin
的分支到本地,于是他用这个命令创建本地dev
分支:
现在,他就可以在dev
上继续修改,然后,时不时的吧dev
分支push
到远程: - 你的小伙伴已经向
origin/dev
分支推送了他的提交,而碰巧你也对同样的文件做了修改,并试图推送:
推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法很简单,Git已经提示我们,先用git pull
把最新的提交从origin/dev
抓下来,然后在本地合并,解决冲突,在推送。 - 然而,
git pull
也失败了,原因是没有指定本地dev
分支与远程origin/dev
分支的链接,根据提示,设置dev
和origin/dev
的连接,再pull。这回git pull
成功,但是合并有冲突,需要手动解决,解决办法和分支管理中的解决冲突完全一样(类似 SVN 解决冲突) 解决后,提交,再push - 因此,多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin branch -name
推送自己的修改 - 如果推送失败,则因为远程分支比你本地更新,需要先用
git pull
试图合并 - 如果合并有冲突,则解决冲突,并在本地提交
- 没有冲突或者解决掉冲突后,再用
git push origin branch -name
推送就能成功
- 首先,可以试图用
- 如果
git pull
提示 “no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name
. - 这就是多人协作的工作模式
- 小结
- 查看远程库信息,使用
git remote -v
- 本地新建的分支如果不推送到远程,对其他人就是不可见的
- 从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交 - 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致 - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
- 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。
- 查看远程库信息,使用
- 当你从远程仓库克隆代码时,实际上Git自动把本地的
-
标签管理
- 创建标签,首先切换到需要打标签的分支上
- 然后输入命令
git tag v1,0
就可以打一个新标签,可以用命令git tag
查看所有标签 - 默认标签是打在最新提交的commit上的,有时间,如果忘了打标签,比如,现在是周五,但应该在周一打的标签没有打,怎么办?方法是找到历史提交的commit id ,然后打上就可以了:
比如,要对add merge
这次提交打标签,看它对应的 commit id 是2f0e36c,键入命令:git tag v.09 <commit id>
,再用命令git tag
查看标签: - 注意,标签不是按时间顺序列出,而是按字母排序的,可以用
git show <tagname>
查看标签信息,可以看到v0.9
确实打在add merge
这次提交上。 - 还可以创建带有说明的标签,用
-a
指定标签名,-m
指定说明文字。用命令git show tagname
可以看到说明文字: - 还可以通过
-s
用私钥签名一个标签。签名采用PGP签名,因此,必须首先安装gpg(GnuPG),如果没有找到gpg,或者没有gpg**对,就会报错,如果报错,请参考GnuPG帮助文档配置key - 用命令
git show <tagname>
可以看到PGP签名信息,用PGP签名的标签是不可伪造的,因为可以验证PGP签名。 - 小结
- 命令
git tag <name>
用于新建一个标签,默认为HEAD
,也可以指定一个 commit id -
git tag -a <tagname> -m "XXX"
可以指定标签信息 -
git tag -s <tagname> -m "XXX"
可以用 PGP签名标签 - 命令
git tag
可以查看所有标签
- 命令
-
操作标签
如果标签打错了,也可以使用
git tag -d <tagname>
命令进行删除:因为创建的标签都只存储在本地,不会自动推送到远程,所以打错的标签可以在本地安全删除
- 如果要推送某个标签到远程,使用命令
git push origin <tagname>
: - 如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除,然后从远程删除,删除命令也是
push
但是要注意格式: - 小结
- 命令
git push origin <tagname>
可以推送一个本地标签 - 命令
git push origin --tags
可以推送全部未推送过的本地标签 - 命令
git tag -d <name>
可以删除一个本地标签 - 命令
git push origin :refs/tags/<tagname>
可以删除一个远程标签
- 命令