git-分支管理
git-分支管理
软件版本:
操作系统:ubuntu10.04
内核版本:Linux version 2.6.32-36-generic
git 版本:git version 1.7.0.4
目录:
1. 介绍
2. 创建分支
3. 切换分支
4. 合并分支
5. 删除分支
6. 分支管理操作
6.1 分支清单
6.2 查看已合并分支
6.3 查看未合并分支
6.4 分支重命名
7. 分支衍合(rebase)
8. 参考资料
1. 介绍
分支本质上其实就是一个指向某次提交的可变指针。git 的默认分支名字为 master 。而我们是怎么知道当前处于哪个分支当中呢?答案就是在于 HEAD 这个十分特殊的指针,它专门用于指向于本地分支中的当前分支。我们可以理解为:
commit <-- branch <-- HEAD
2. 创建分支
当我们需要调试某个 BUG 或者尝试添加或修改程序中的某个模块,而又不能影响主分支的开发时。就可以通过创建分支来满足需求。
创建分支相当于是创建一个新的分支指针指向当前所在的提交。例如我们在 Commit_3 上创建分支 Branch_1 :
$git branch Branch_1
如图所示,Branch_1 指向提交 Commit_3 。
从上图可知,虽然我们创建了一个新分支,但是 HEAD 仍然指向 master 。如果希望在创建分支的同时切换到新分支上,我们可以通过以下命令实现:
$git checkout -b Branch_1
HEAD 指向 Branch_1 。
3. 切换分支
在项目开发的过程中,分支之间的切换是一件非常普遍的事情。比如在某分支上调试 BUG ,突然需要在主分支中添加点代码,就需要在分支间进行切换。
分支之间的切换其实就是使 HEAD 指向指定的分支,以后的提交将从属于该分支。切换命令为:
$git checkout Branch_1
这时候进行提交的话,那么这次的提交就是属于 Branch_1 分支的。
4. 合并分支
当某分支上的工作完成了,那么就需要合并到其它分支上。分支合并命令为:
$git merge branch_name
现在我们要对下面的项目进行一次合并分支的演示:
将 branch_1 合并到 master 主分支上:
$git merge branch_1
Auto-merging file
CONFLICT (content): Merge conflict in file
Automatic merge failed; fix conflicts and then commit the result.
$git status
# On branch master
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: file
#
no changes added to commit (use "git add" and/or "git commit -a")
由于 commit_3 和 B_C_1 这两次提交都修改了同一个文件,所以在合并的过程中就会产生冲突,需要我们手动解决。git status 中 Unmerged paths: 这栏告诉我们哪些文件在合并的过程中产生冲突。
git 会在有冲突的文件中加入标记,file 的内容会变为:
commit_1
<<<<<<< HEAD
commit_2
=======
branch_1 commit 1
>>>>>>> branch_1
可以看到文件的一部分内容被 ======= 分隔开,上半部分是 HEAD 的内容,下半部分就是 branch_1 中的内容。你可以直接修改该文件来解决冲突,也可以通过 git mergetool 命令来解决。
我们可以使用 git mergetool 来解决这个事情。
$git mergetool
merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis emerge vimdiff
Merging the files: file
Normal merge conflict for 'file':
{local}: modified
{remote}: modified
Hit return to start merge resolution tool (meld):
在我的环境中,默认使用 meld 来解决合并冲突。我们来看一下解决完之后的 git 状态:
$git status
# On branch master
# Changes to be committed:
#
# modified: file
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# file.orig
git 状态显示 file 已经被放入到暂存区里了,只需要提交一下就可以了。file.orig 是一个备份文件。
$git commit
[master 3f8596e] Merge branch 'branch_1'
$git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# file.orig
nothing added to commit but untracked files present (use "git add" to track)
提交后我们来看一下提交日志。
$git lg
* 3f8596e00cbd01320a31c0e7e2715ac12dffc48c @ (HEAD, master)
|\ Author: Eddy <he_jianfa@126.com>
| | Date: Thu Mar 29 11:02:22 2012 +0800 (15 seconds ago)
| |
| | Commit subject: Merge branch 'branch_1'
| |
| * 6d5867c77debde72d12f3187ab972944f88624be @ (branch_1)
| | Author: Eddy <he_jianfa@126.com>
| | Date: Thu Mar 29 10:25:50 2012 +0800 (37 minutes ago)
| |
| | Commit subject: branch_1: commit 1
| |
* | c773ca7c9a0154876b7de4ed66cabe704da6f29d @
|/ Author: Eddy <he_jianfa@126.com>
| Date: Tue Mar 27 08:58:52 2012 +0800 (2 days ago)
|
| Commit subject: commit_2
|
* c438c48d1cd9615490d8be830683487de858e7b3 @
Author: Eddy <he_jianfa@126.com>
Date: Tue Mar 27 08:51:54 2012 +0800 (2 days ago)
Commit subject: commit_1
合并提交后,branch_1 仍然指向原来的 commit 。示意图:
5. 删除分支
被合并后的分支自然就失去了它存在的意义了,现在我们来把 branch_1 分支删除掉。
$git branch -d branch_1
Deleted branch branch_1 (was 6d5867c).
6. 分支管理操作
下面来介绍一些关于分支管理中的一些常用操作。
6.1 分支清单
$ git branch
branch_1
branch_2
* master
带 * 号的分支表示是当前分支。
6.2 查看已合并分支
$ git branch --merged
branch_1
* master
6.3 查看未合并分支
$ git branch --no-merged
branch_2
6.4 分支重命名
$git branch -m branch_2 branch_renamed
7. 分支衍合(rebase)
衍合(rebase)其实就是以补丁的形式将当前分支打到指定的分支上,最后当前分支会和指定分支结合在一起。它与合并(merge)的区别就在于当前分支会和指定分支合并在一起并产生一个新的提交,使得整个 git 项目看起来更加整洁;而 merge 则会保留所有的分支提交记录。
假如我们对下图所示的 git 项目进行衍合。
将会达到下面的结果。
我们现在来演示一下具体的操作过程,假设我们正处在 branch_1 分支中。现在要和 master 分支进行衍合。
$git rebase master
First, rewinding head to replay your work on top of it...
Applying: branch_1
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging file
CONFLICT (content): Merge conflict in file
Failed to merge in the changes.
Patch failed at 0001 branch_1
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".
在衍合的过程中会对文件进行合并,从上面的打印可以看出在合并的过程中出现冲突,导致衍合失败。利用第四节中提到的方法解决该冲突,然后根据上面的打印提示继续衍合。
$git mergetool
merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis emerge vimdiff
Merging the files: file
Normal merge conflict for 'file':
{local}: modified
{remote}: modified
Hit return to start merge resolution tool (meld):
$git rebase --continue
Applying: branch_1
衍合完成后,当前正处在 branch_1 分支上,如图所示:
然后我们就需要回到 master 分支上,将 master 与 branch_1 合并。
$git checkout master
Switched to branch 'master'
$git merge branch_1
Updating 12c963d..82d3623
Fast-forward
file | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
最终就达到我们想要的结果了。
$git status
# On branch master
nothing to commit (working directory clean)
$git lg
* 82d36231ff46f362885a8a369cb80cf95009058a @ (HEAD, master, branch_1)
| Author: Eddy <he_jianfa@126.com>
| Date: Thu Mar 29 17:48:58 2012 +0800 (37 seconds ago)
|
| Commit subject: branch_1
|
* 12c963d83d23a7ffc78ca2e13935b5d36fbf5d76 @
| Author: Eddy <he_jianfa@126.com>
| Date: Thu Mar 29 16:22:39 2012 +0800 (87 minutes ago)
|
| Commit subject: commit 3
|
* 0850a6759874ed23042cb0fddb43b5c7d28e5b7b @
| Author: Eddy <he_jianfa@126.com>
| Date: Thu Mar 29 16:21:19 2012 +0800 (88 minutes ago)
|
| Commit subject: commit 2
|
* 82e24403d7b4a562dedf343955df8196fe353bf6 @
Author: Eddy <he_jianfa@126.com>
Date: Thu Mar 29 16:20:59 2012 +0800 (89 minutes ago)
Commit subject: commit 1
与第四节的分支合并结果对比,整个 git 项目确实要整洁许多。
8. 参考资料
[1] 《pro git》