Git学习笔记之分支管理
书接上回,本文主要介绍Git
的分支管理操作。
Git
的分支功能为我们团队分工提供了方便,并且每一个分支在合并之前不会对另外的分支产生影响:
与分支管理相关的命令:
命令 | 说明 | 命令 | 说明 |
---|---|---|---|
git branch (branchname) | 创建分支 | git checkout/switch (branchname) | 切换分支 |
git merge (branchname) | 合并指定分支 | git branch | 列出所有分支 |
git branch -d (branchname) | 删除指定分支 |
Git
默认给我们生成了一个master
主分支
$ git branch
* master
我们之前说的HEAD
指向当前版本,严格来说是指向master
,而master
指向的是该分支的最新提交,因此HEAD
指向的是最新提交,熟悉类C
语言的指针相关知识应该很容易理解这部分内容。
使用分支
新建分支
新建一个前端分支front
$ git switch -c front
Switched to a new branch 'front'
-c
代表新建一个分支switch
代表切换分支
确保当前所在分支
$ git branch
* front
master
在该分支下新建我们的文件front.txt
,并提交
$ touch front.txt
$ git add front.txt
$ git commit -m "new front branch"
我们再转回主分支master
$ git switch master
Switched to branch 'master'
此时我们会发现我们之前新建的front.txt
文件不见了,这是因为该文件是在front
分支下提交的,此时的前端分支比我们的主分支“提前”。
同样的方法新建一个接口分支并加一个文件
$ git switch -c interface
Switched to a new branch 'interface'
$ touch interface.txt
$ git add interface.txt
$ git commit -m "new interface branch"
[interface 824a607] new interface branch
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 interface.txt
$ git switch master
Switched to branch 'master'
此时仓库情况如图:
合并分支
两边的人员工作都做完了,就可以考虑合并了,毕竟一直单干啥事都干不了
$ git merge front
$ git merge interface
意思是依次将当前分支(即master
)合并到目标分支,我们尝试合并第二个时可能会遇到下面的情况
Merge branch 'interface'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
意思是说希望我们能够给出合理的解释,为什么要合并这两个分支,我们可以直接关闭( 按键盘左上角Esc
,输入:wq
即可退出)也可以写入一些信息( 按键盘字母 i
进入insert
模式并输入说明然后关闭 )
merge front and interface
然后我们的当前主分支下就会出现front.txt
和interface.txt
两个文件了。
删除分支
我们合并好分支后,对于不需要的分支可以删除,不会对我们目前的分支产生影响,因为我们当前的主分支比两个分支都“提前”,删除实际上删除的是指针。
$ git branch -d front
Deleted branch front (was 0c93a6f).
$ git branch -d interface
Deleted branch interface (was 824a607).
$ git branch
* master
$ git log
commit 844e6a7ef9d46e3386bb0e18fecef93121f1831c (HEAD -> master)
Merge: 0c93a6f 824a607
Author: YaleXin <495592364@qq.com>
Date: Wed Feb 9 15:03:51 2022 +0800
merge front and interface
commit 824a60792b798f2ae9dfb55859142c41773573ad
Author: YaleXin <495592364@qq.com>
Date: Wed Feb 9 14:45:35 2022 +0800
new interface branch
commit 0c93a6f1f8ca2c884040437b3568514518ffbb7a
Author: YaleXin <495592364@qq.com>
Date: Wed Feb 9 14:37:57 2022 +0800
new front branch
:
可以发现我们的提交都没有丢失
解决冲突
当然了合并也不是每一次都能愉快地进行,不然前后端之间的矛盾也不会有这么多了。
假如前端说JavaScript
是世界上最好的语言!
$ git switch -c front
Switched to a new branch 'front'
新建lan.txt
文件并在文件中输入
`JavaScript`是世界上最好的语言!
然后提交
$ git add .
warning: LF will be replaced by CRLF in lan.txt.
The file will have its original line endings in your working directory
$ git commit -m "最好的语言"
[front 2ba9fe4] 最好的语言
1 file changed, 1 insertion(+)
create mode 100644 lan.txt
而后端的人却说Java
是世界上最好的语言!
$ git switch master
Switched to branch 'master'
新建lan.txt
文件并在文件中输入
`Java`是世界上最好的语言!
然后提交
$ git add .
warning: LF will be replaced by CRLF in lan.txt.
The file will have its original line endings in your working directory
$ git commit -m "最好的语言"
[master 8ee9862] 最好的语言
1 file changed, 1 insertion(+)
create mode 100644 lan.txt
然后尝试合并
$ git merge front
Auto-merging lan.txt
CONFLICT (add/add): Merge conflict in lan.txt
Automatic merge failed; fix conflicts and then commit the result.
这可把Git
难住了,不同的分支对同一文件有不同的修改方式,Git
尽最大能力也无法将其合并,现在只能我们自己手动合并冲突了。
我们打开lan.txt
文件可以发现
$ cat lan.txt
<<<<<<< HEAD
`Java`是世界上最好的语言!
=======
`JavaScript`是世界上最好的语言!
>>>>>>> front
上面表明<<<<<<<
和=======
之间的是当前分支的内容,=======
和>>>>>>>
之间的是front
分支的内容,我们手动将其改成
自然语言是世界上最好的语言!
然后提交
$ git add .
$ git commit -m "你们俩别吵了"
[master 7cec3a6] 你们俩别吵了
$ git log
commit 7cec3a623357cbea756a12235a995df2f85d6eed (HEAD -> master)
Merge: 8ee9862 2ba9fe4
Author: YaleXin <495592364@qq.com>
Date: Wed Feb 9 16:06:57 2022 +0800
你们俩别吵了
commit 8ee98627480b081d1885f8adcb7aad9580c2910c
Author: YaleXin <495592364@qq.com>
Date: Wed Feb 9 15:55:50 2022 +0800
最好的语言
commit 2ba9fe41d1379e4d57077f6d76ba7ed7e4ec55cd (front)
Author: YaleXin <495592364@qq.com>
Date: Wed Feb 9 15:51:01 2022 +0800
最好的语言
分支管理策略
开发分支
通常,合并分支时,如果没有冲突,并且分支是单向一条线路继承下来的,git会使用 fast forword
模式,但是有些快速合并不能成功,但是又没有冲突时,就会触发分支管理策略,Git
会自动做一次新的提交。
当然我们也可以手动强制禁用Fast forward
模式,Git
就会在merge
时生成一个新的commit
.
我们来看一下区别:
首先新建一个分支并修改lan.txt
,然后使用默认方式合并
$ git switch -c default
Switched to a new branch 'default'
修改lan.txt文件
$ git add .
$ git commit -m "default commit"
[default e167bc0] default commit
1 file changed, 1 insertion(+), 1 deletion(-)
$ git switch master
Switched to branch 'master'
$ git merge default
Updating 7cec3a6..e167bc0
Fast-forward
lan.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
我们再查看提交情况:
$ git log --pretty=oneline --abbrev-commit --graph
* e167bc0 (HEAD -> master, default) default commit
* 7cec3a6 你们俩别吵了
|\
| * 2ba9fe4 最好的语言
* | 8ee9862 最好的语言
|/
* 844e6a7 merge front and interface
|\
| * 824a607 new interface branch
* | 0c93a6f new front branch
|/
* dcfdaa2 3
* e54198e second commit
* bbe2a77 first commit
合并情况如图所示
让我们再来个禁用Fast forward
模式的合并
新建一个分支并修改lan.txt
,然后使用禁用Fast forward
模式合并
$ git switch -c noFast
Switched to a new branch 'noFast'
修改lan.txt文件
$ git add .
$ git commit -m "noFast commit"
[noFast f7f1ef6] noFast commit
1 file changed, 2 insertions(+), 1 deletion(-)
$ git switch master
Switched to branch 'master'
$ git merge --no-ff -m "merge by no-ff" noFast
Merge made by the 'ort' strategy.
lan.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
$ git log --pretty=oneline --abbrev-commit --graph
* 274515d (HEAD -> master) merge by no-ff
|\
| * f7f1ef6 (noFast) noFast commit
|/
* e167bc0 (default) default commit
* 7cec3a6 你们俩别吵了
|\
| * 2ba9fe4 最好的语言
* | 8ee9862 最好的语言
|/
* 844e6a7 merge front and interface
|\
| * 824a607 new interface branch
* | 0c93a6f new front branch
|/
* dcfdaa2 3
* e54198e second commit
* bbe2a77 first commit
合并情况如图所示
即会自动提交一次。
有了上述清晰的认识以后,我们以后在日常使用Git
开发的时候应该要秉承在master
尽量少提交的理念,即尽可能稳定,最好只用来发布版本,然后在分支dev
上进行日常开发,每逢大版本更新的时候再把它合并到主分支上面;当然了,在分工明确的前提下,每个人应该至少有属于自己的分支,然后定期合并到dev
。
临时分支
前面讲到版本库的两条主要分支:master
和dev
。前者用于正式发布,后者用于日常开发。其实,常设分支只需要这两条就够了,不需要其他了。
但是,除了常设分支以外,还有一些临时性分支,用于应对一些特定目的的版本开发。临时性分支主要有三种:
- 功能(
feature
)分支 - 预发布(
release
)分支 - 修补bug(
fixbug
)分支
这三种分支都属于临时性需要,使用完以后,应该删除,使得代码库的常设分支始终只有master
和dev
。
功能分支
它是为了开发某种特定功能,从dev
分支上面分出来的,开发完成后,要再并入dev
, 功能分支的名字,可以采用feature-name
的形式命名。
预发布分支
预发布分支,它是指发布正式版本之前(即合并到master
分支之前),我们可能需要有一个预发布的版本进行测试。预发布分支是从dev
分支上面分出来的,预发布结束以后,必须合并进dev
和master
分支。它的命名,可以采用release-*
的形式。
修补分支
软件正式发布以后,难免会出现bug
。这时就需要创建一个分支,进行bug
修补。
修补bug
分支是从master
分支上面分出来的。修补结束以后,再合并进master
和deev
分支。它的命名,可以采用fixbug-*
的形式。
这里有一个场景,你手头上的工作还没做完,但是你接到一个比较紧急的修复任务的时候,你又不想暂时提交这半截子代码,该怎么办?
Git
提供了stash
命令,它把所有未提交的修改(包括暂存的和非暂存的)都保存起来,用于后续恢复当前工作目录。
$ git status
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: front.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git stash
Saved working directory and index state WIP on dev: 274515d merge by no-ff
$ git status
On branch dev
nothing to commit, working tree clean
等我们在新的分支上修复好BUG
,并合并好分支,然后再将这个暂时的修复分支删除后,就可以切换到我们的dev
分支上来继续我们的工作了。
可以看一下之前暂存的代码
$ git stash list
stash@{0}: WIP on dev: 274515d merge by no-ff
$ git status
On branch dev
nothing to commit, working tree clean
回复我们的工作有两种方法:
- 用
git stash apply
恢复,但是恢复后,stash
中的内容并不删除,你需要用git stash drop
来删除 - 用
git stash pop
,该方法在恢复的同时把stash
中的内容也删了:
$ git stash pop
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: front.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (414125ba81aaed29ef4736209c257077fb277202)
然后我们就可以继续愉快地进行我们的工作了。
本文由「黄阿信」创作,创作不易,请多支持。
如果您觉得本文写得不错,那就点一下「赞赏」请我喝杯咖啡~
商业转载请联系作者获得授权,非商业转载请附上原文出处及本链接。
关注公众号,获取最新动态!