Git分支功能
Git的主要分为主分支master
,开发分支develop(dev)
,辅助分支dev-*,release-*,hotfix-*
- 主分支(master)
作用:开发者可以从主分支上发布新版本,也可以获得线上代码 - 开发分支(develop)
作用:开发者将自己的分支首先合并到开发分枝上,也可以从开发分枝上获得最新开发的代码 - 辅助分支(dev-*,release-*,hotfix-*)
作用:
Feature branches:“管理功能开发”的分支,命名以`dev-`开头,用于开发版本新功能,完成后合并至develop分支
Release branches:“帮助构建可发布代码”的分支,命名以`release-`开头,从develop上面拉取,用于与发布新版本和修复预发布版本bug,完成后分别合并至master和develop分支
Hotfix branches:“便捷修复发布版本Bug分支”,命名以`hotfix-`开头,从master分支上拉取,用于快速修复线上Bug,完成后分别合并至master和develop分支
分支产生的原因:
1.需要开发这对一个项目进行并行开发
2.修复旧版本中的bug
就像上面的AB,就创建了各自的分支,别人看不到,还可以在原来的分支上面继续工作,等到最后可以合并在一起,即安全,又高效。
创建合并分支
-
每次提交,Git都会把它们串成一条时间线,这个时间线就是一个分支,每个都会有一个
master
分支,叫做主分支,默认HEAD开始指向主分支,Git用master指向最新的提交
-
当我们创建新的分支时,比如
dev
,Git就新建了一个指针dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分值在dev
上
-
Git创建一个分支很快,新增一个
dev
指针,在改变HEAD指向即可,工作区的文件没有变化
但是从切换分支开始,对工作区的修改和提交就针对dev
分支了,每次新的提交,dev
就向前移动一次,master
指针不移动
-
dev
分支的工作完成之后想要和master
分支合并,只需要把master
指针,指向当前dev
的提交即可,这样就完成了合并
-
合并分之后,也可以删除
dev
分支。删除dev
分支,就是删除dev
指针
命令
创建分支:git branch
切换分支:git checkout
查看分支:git branch
创建+切换分支:git checkout -b
合并某分支到当前分支:git merge
删除分支:git checkout -d
eg:
1.创建dev
分支,并切换到dev
分支
》 git branch dev 创建分支
> git checkout dev 切换到dev分支
或者
> git checkout -b dev 创建并合并分支
2.git branch
列出所有分支,Git版本库中总是存在着唯一一个活动分支,用星号(*)标记的就是当前活跃的分支
> git branch
* dev
master
3.在dev
分支下修改文件file1并提交修改,切换回master
分支,你会发现file1文件并没有做任何修改
> git branch 查看目前位于哪个分支(此时为master分支)
dev
* master
> cat file1 查看master分支下file1文件内容
hello world!
> git checkout dev 切换到dev分支
Switched to branch 'dev'
> echo "I love china" >> file1 修改文件file1(这是追加了一句)
> git add file1
> git commit -m "I love china" 提交修改
[dev b8a482b] I love china
1 file changed, 1 insertion(+)
> git checkout master 再次切换到master分支
Switched to branch 'master'
> cat file1 查看file1内容,你会发现内容没有改变
hello world!
4.dev
分支工作结果可以合并到master
分支上了
- 切换分支错误
切换分支可能会失败,这是因为我们当前分支工作区、暂存区存在一些修改,并且没有确认提交
> git checkout master
error: Your local changes to the following files would be overwritten by checkout:
file1
Please, commit your changes or stash them before you can switch branches.
Aborting
解决方法:
1.提交修改后切换
> git commit --all
> git checkout master
2.放弃这部分修改并切换
> git checkout --force master
--force强制切换
-
git merge
合并分支
> git merge dev
Updating 9c4b701..614031d
Fast-forward
hello.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
上面信息中有一个Fast-forward
,意思是此次合并是“快进模式”。就是把master
指针指向dev
分值的当前提交,所以合并非常快,Git默认是这种提交模式
5.git branch -d
删除分支
git branch -d dev
Deleted branch dev (was ed7a0b9).
> git branch 只剩下master分支
* master
分支冲突:
编辑冲突:
我们可能会多个人在不同分支上对同一个文件的同一处做不同修改,这时Git不知道采用哪一个,就会出错误
树木冲突:
一个分支修改了内容, 另个一分支删除了文件, 在试图合并时就会出现树冲突。假设子分支(如 dev)是要合并到主分支 master 的, 处理的方法有:
(1)放弃 dev 的修改:强制删除 dev 分支, 然后提交即可。
(2)放弃 master 的修改----分下面两种情况:
master 修改了内容, dev 删除了文件:
在 master 分支中删除该文件, 然后提交;
master 删除了文件, dev 修改了内容: 在 master 分支中添加被修改的文件, 然后提交。
eg:编辑冲突
创建新的分支branch2
,修改文件file1,
> git checkout -b branch2
> echo "my name is ymd" >> file1
在分支branch2
上提交修改
> git add file1
> git commit -m "branch2 commit"
切换到master
分支,之后修改文件file1并提交
> git checkout master
> echo "my name is xiaoyin" >> file1
> git add file1
> git commit -m "master file1"
这时,master
分支和branch2
分支都有一次提交
合并分支
> git merge branch2
Auto-merging file1
CONFLICT (content): Merge conflict in file1
Automatic merge failed; fix conflicts and then commit the result.
现在,Git不能执行“快速合并”,只能试着把各自的修改合并起来,但是这种合并往往会产生冲突
- 解决编辑冲突:
为了方便查看冲突我们可以将git配置成三路模式
> git config merge.conflictstyle diff3
1.启动合并工具
> git mergetool
或者手动合并
a:编辑受影响的文件
b:采用--ours或者--theirs选项,选择只选用自己或者别人那个版本的文件
> git checkout --theirs
2.提交修改
> git add .
> git commit -m ""
当然我们也可以取消合并
> git reset --merge
-
--no-ff
合并时禁用Fast forward
模式
通常git在合并分支采用的是Fast forward
模式,就是合并之后删除分支,会丢掉分支信息,如果强制禁止了Fast forward
模式,Git就会在合并时生成一个新的commit,使得我们能在分支历史上看出分支信息。
# git merge --no-ff -m "no-ff" dev
在实际应用中,master
分支应该是非常那个稳定的,只用来发布新版本,平时不能在上面工作,需要另选一个分支,比如dev
,就是大家合并版本到dev
分支上,只有新版本发布时,再把最新版本从dev
合并到master
分支上
开发一个新功能最好创建一个新分支
- 编辑冲突
# git merge brnach2
fatal: brnach2 - not something we can merge
-
git checkout -D
强制删除一个从未合并过的分支
变基Rebase
- 避免钻石链
如上图所示,一个项目会多个开发者多次提交,这样就存在许多杂乱的分支,Git用rebase
命令帮我们理顺这些历史记录,篡改历史记录
所有rebase操作对象都是commit,但是未push到公共仓库,变基后在没有gc时,还可以通过原来的散列值访问原来的分支
# git rebase master
- 移值分支
移值不属于原分支的版本
前期:
移植后:git rebase master --onto relase1
# git checkout dev切换到待移动分支
# git log master..dev
或者直接在原分支上查看
# git checkout master
# git log HEAD..dev显示在dev上而不在当前分支的提交
# git rebase master --onto relase1
rebase命令的第一个参数所指定的是原分支(这里是master分支),然后,Git会确认dev上面所有不属于原分支的提交(这里是E和F),最后通过--onto选项将这些提交拷贝到指定位置上(这里是release1分支)
一次完整的移植合并分支:
1.原本的分支:
2.现在我需要将client
分支上做的改变而非server
上面的改变(A8和A9),直接在master
分支中重演一遍
# git rebase --onto master server client
取出client分支,找出client分支和server分支共同祖先之后的变化,然后把他们在master上面重放一遍(server和client这两个分支修改的应该是不同的文件)
3.快进master
分支:
# git checkout master
# git merge client
4.现在把server
分支的变化也包含进来。我们可以直接把server
分支变基到master
分支
git rebase <主分支> <特性分支>
先取出特性分支,比如server,再到主分支master
上重演
# git rebase master server
所以,server分支的进度应用到master基础上,如下图所示:
5.快进主干分支:
# git checkout master
# git merge server
6.删掉client和server分支
# git branch -d clien
# git branch -d server
7.最后的提交历史
- rebase冲突解决
rebase命令和merge命令一样会在相关修改不匹配的时候发生冲突
1.手动解决或者通过合并工具解决,将他们从新添加至暂存区
然后执行rebase命令,加上--continue选项,从该点继续之前的进程
# git add file1
# git add file2
# git rebase --continue
2.选项--abort
选项取消这次rebase命令
3.选项--skip
选项跳过引起这次冲突的提交