分支管理
创建与合并分支
Git的分支是非常强大的工具,在开发新功能或修复缺陷,均推荐使用分支来进行处理。在Git中创建、切换和删除分支都非常快速,下面开始进行实际操作。
首先创建一个新的分支dev
# git checkout -b dev
切换到一个新分支 'dev'
git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
然后,用git branch命令查看当前分支,git branch命令会列出所有分支,当前分支前面会标一个*号:
# git branch
* dev
master
git merge命令用于合并指定分支到当前分支:
# git merge dev
更新 910d66b..98cd448
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
合并完成后,删本地dev分支:
# git branch -d dev
已删除分支 dev(曾为 98cd448)。
删除远程dev分支:
# git push origin --delete dev
To github.com:daiwuliang/learngit.git
- [deleted] dev
解决冲突
当同一个文件在不同分支修改出现冲突时,Git就无法进行快速合并,这样必须进行手工解决冲突。
当冲突情况下进行分支合并,会提示文件冲突:
# git merge dev
自动合并 readme.txt
冲突(内容):合并冲突于 readme.txt
自动合并失败,修正冲突然后提交修正的结果。
此时也可以运行git status查看状态,同样会显示冲突文件:
# git status
位于分支 master
您的分支领先 'origin/master' 共 3 个提交。
(使用 "git push" 来发布您的本地提交)
您有尚未合并的路径。
(解决冲突并运行 "git commit")
(使用 "git merge --abort" 终止合并)
未合并的路径:
(使用 "git add <文件>..." 标记解决方案)
双方修改: readme.txt
此时打开冲突文件,Git会在其中标注出冲突的内容:
1 Git is a version control system
2 Git is a free software
3 Git is distrubuted
4 Git is a good tool
5 dev branch content
6 <<<<<<< HEAD
7 test2
8 =======
9 test1
10 >>>>>>> dev
解决冲突需要人工进行确认,保留其中某个分支内容或者进行融合,只需要人工进行修改后再次提交文件:
# git add readme.txt
# git commit -m 'confilct fixed'
[master d4a9dbc] confilct fixed
用带参数的git log也可以看到分支的合并情况:
# git log --graph
* commit d4a9dbcaf563b71c9fce802b56c575371b52d7cc (HEAD -> master)
|\ Merge: 7a466c5 2b5ffd8
| | Author: daiwuliang <daiwuliang@126.com>
| | Date: Sun Dec 29 13:14:40 2019 +0800
| |
| | confilct fixed
| |
| * commit 2b5ffd89dc6d5076ea4e332648e02ee6cbd6d990 (dev)
| | Author: daiwuliang <daiwuliang@126.com>
| | Date: Sun Dec 29 13:05:54 2019 +0800
| |
| | dev commit
| |
* | commit 7a466c572cd4df48de844ab8e59ee8a200b435dd
|/ Author: daiwuliang <daiwuliang@126.com>
| Date: Sun Dec 29 13:06:31 2019 +0800
|
| master commit
|
* commit 98cd448a79c6267f0447b73b7bd1d587a8cf2f29
| Author: daiwuliang <daiwuliang@126.com>
| Date: Sun Dec 29 12:53:42 2019 +0800
|
| test dev
|
* commit 910d66be806f054c770784f71b342963a052b446
| Author: daiwuliang <daiwuliang@126.com>
| Date: Sun Dec 29 11:36:58 2019 +0800
|
| modify file
|
* commit 240e6044c9a39bb1619997ddff93c5a315a8d421 (origin/master)
| Author: daiwuliang <daiwuliang@126.com>
| Date: Sun Dec 29 11:34:02 2019 +0800
|
| testfile
|
* commit f61ccfd72c93ee2e8d5a89445dee14b26f9d4ddb
| Author: daiwuliang <daiwuliang@126.com>
| Date: Sat Dec 28 22:59:20 2019 +0800
|
| delete file
|
* commit 092014d670e663b850ba6d4e821d2114e8f5fccc
| Author: daiwuliang <daiwuliang@126.com>
| Date: Sat Dec 28 19:55:16 2019 +0800
|
| test
|
* commit 4ea274f2de3c5268bb547d966fa78c36c7cbd543
| Author: daiwuliang <daiwuliang@126.com>
| Date: Sat Dec 28 19:50:21 2019 +0800
|
| test modify
|
* commit e90b490b4351d0b58716586a2fd0d92f551438eb
Author: daiwuliang <daiwuliang@126.com>
Date: Sat Dec 28 19:36:30 2019 +0800
first commit
Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息,如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息,以下为禁用Fast Forward模式的合并:
git merge --no-ff -m "merge with no-ff" dev
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
BUG分支
在Git中,bug可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
但如果当前dev分支仍然有未完成的工作,导致存在未提交的内容,在此时可以通过stash功能将工作现场储藏起来,修复bug后再进行恢复:
# git stash
保存工作目录和索引状态 WIP on dev: d4a9dbc confilct fixed
此时再查看工作区状态,则为干净的工作区
# git status
位于分支 master
您的分支与上游分支 'origin/master' 一致。
无文件要提交,干净的工作区
此时可以创建bug分支,进行修改提交后,合并至master分支:
#git checkout - b issue-001
#git add .
#git commit -m 'bug001'
#git checkout master
#git merge issue-001
此时bug已经修复提交,切换回dev分支,此时工作区是干净的,用git stash list命令查看现场历史:
#git stash list
stash@{0}: WIP on dev: f52c633 add merge
恢复刚才的工作现场,有两种办法:
一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
另一种方式是用git stash pop,恢复的同时把stash内容也删了:
#git stash apply
#git stash drop
#git stash pop
你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:
#git stash apply stash@{0}
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick “commitid
” 命令,只把bug提交的修改“复制”到当前分支,避免重复劳动。
删除未合并的分支
因为某些原因,要删除一些未合并的分支,git branch -d branchname并不能生效,需要根据提示用以下命令:
$ git branch -D branchname
多人协作
当从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin。
要查看远程库的信息,用git remote:
# git remote
origin
或者,用git remote -v显示更详细的信息:
# git remote -v
origin git@github.com:daiwuliang/learngit.git (fetch)
origin git@github.com:daiwuliang/learngit.git (push)
上面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。
- 推送分支
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
如果要推送其他分支,比如dev,就改成:
$ git push origin dev
但是,并不是一定要把本地分支往远程推送,有些分支完全可以只存在与本地。
- 抓取分支
当想创建远程origin的dev分支到本地,可以用这个命令创建本地dev分支:
$ git checkout -b dev origin/dev
此时就可以在本地进行修改提交,通过git push命令推送至远程仓库
若想获取远程仓库的内容,使用git pull命令:
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> dev
git pull如果失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:
$ git branch --set-upstream-to=origin/dev dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
之后在git pull即可以获取成功,如果有冲突则需要解决冲突,方法与之前提过的一致,但此时解决冲突查看git log,则会发现提交记录有分支,因为我本地master的提交历史和远端的master分支的提交历史不一致,所以git为我进行了自动合并,然后生成了一个新的提交历史,此时可以使用git rebase,把本地未push的分叉提交历史整理成直线:
$ git rebase
因此,多人协作的工作模式通常是这样:
-
首先,可以试图用git push origin 推送自己的修改;
-
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
-
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/。