一个计算机技术爱好者与学习者

0%

好好学Git:Git分支

1. 前言

Branches in Git are incredibly lightweight as well. They are simply pointers to a specific commit – nothing more. This is why many Git enthusiasts chant the mantra:

branch early, and branch often.

Because there is no storage / memory overhead with making many branches, it’s easier to logically divide up your work than have big beefy branches.

When we start mixing branches and commits, we will see how these two features combine. For now though, just remember that a branch essentially says “I want to include the work of this commit and all parent commits.”

参考文档:

2. git分支规范

参考文档:

3. 分支基本操作

3.1. 查看分支

1
git branch -a

3.2. 本地仓库中创建分支

本地仓库中创建与当前分支相同的bugfix分支,并切换到bugfix分支

1
2
3
git checkout -b bugfix
# or
git branch bugfix && git checkout bugfix

创建与本地仓库main分支相同的分支

1
git checkout main -b bugfix

创建与远程仓库main分支相同的分支,追踪远程分支

1
git checkout origin/main -b bugfix

3.3. 切换分支

下载仓库后,切换到bugfix分支,bugfix分支追踪远程 origin/bugfix 分支

1
2
git pull
git checkout origin/bugfix

3.4. 远程仓库中创建分支

创建远程仓库bugfix分支和bugfix2分支

1
2
git push origin HEAD:bugfix
git push origin HEAD:bugfix2

3.5. 上传分支

在bugfix分支下进行了修改,然后提交修改

1
2
3
git add .
git commit -m "something"
git push origin HEAD:bugfix

3.6. 删除分支

1、删除本地分支

1
git branch -D bugfix

2、删除远程分支

1
git push --delete origin bugfix

4. 恢复已删除分支

1、查看全局日志

1
git reflog

或者

1
git log -g

2、新建分支

1
git branch bugfix 3eac14d

3、上传分支

1
2
git checkout bugfix
git push origin HEAD:bugfix

5. 合并分支

5.1. 合并分支概述

合并分支,可以使用merge,也可以使用rebase。它们俩有什么区别呢?主要是适用场景不同:

场景一:基于 master 拉出来一个开发分支 dev,在 dev 分支开发完成了之后,要合并到 master 上。
操作:切换到 master 分支,使用 git merge dev
PS:对于git服务器端的merge合并,往往要发起MR,也就是Merge Request
为什么不使用git rebase dev?因为master是主干,rebase的话,主干就长歪了。为了保证master提交记录是笔直的主干,是一条直线,所以使用merge。

场景二:基于 master 拉出来一个开发分支 dev,在 dev 上开发了一段时间后,master分支也有了新的变更。为了保证我们在最新的版本基础上进行开发,这时需要把 master 分支提交的新内容更新到 dev 分支。
操作:切换到 dev 分支,使用 git rebase master
为什么不使用git merge master?因为dev最终是要merge到master的,如果master先merge到dev,开发一段时间后dev最后又merge到master,整个提交树会很混乱。为了保证提交记录的清晰明了,所以使用rebase。

查看提交树命令:git log --graph --pretty=oneline

5.2. 模拟分支变更

1、初始化仓库和分支

1
2
3
4
5
6
7
mkdir test
cd test
git init
touch test.txt
git add .
git commit -m "first commit"
git checkout -b bugfix

2、bugfix分支上,新建test.txt文件,提交

1
2
3
echo "hello bugfix" > test.txt
git add .
git commit -m "update file in bugfix branch"

3、切到master分支,新建test.txt文件,提交

1
2
3
4
git checkout master
echo "hello master" > test.txt
git add .
git commit -m "update file in master branch"

5.3. merge

1、通过merge命令合并bugfix分支到master

1
git merge bugfix

提示冲突:

1
2
3
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.

2、查看冲突
git status,提示test.txt文件冲突。
打开test.txt,可以看到如下冲突:

1
2
3
4
5
<<<<<<< HEAD
hello master
=======
hello bugfix
>>>>>>> update file in bugfix branch

其中 ======= 隔开的上半部分,是 HEAD(即 master 分支,在运行 merge 命令时检出的分支)中的内容,下半部分是在bugfix分支中的内容。解决冲突的办法无非是二者选其一或者由你亲自整合到一起。

3、解决冲突
修改test.txt如下:

1
hello master

4、提交

1
2
git add test.txt
git commit -m "merge bugfix into master"

5、查看提交记录

1
git log

5.4. rebase

5.4.1. rebase合并内容

需求:text.txt 打算合并master分支和bugfix分支中的内容。
text.txt最终内容为:

1
hello master bugfix

1、通过rebase命令合并master分支到bugfix

1
2
git checkout bugfix
git rebase master

提示冲突:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
First, rewinding head to replay your work on top of it...
Applying: update file in bugfix branch
Using index info to reconstruct a base tree...
M test.txt
Falling back to patching base and 3-way merge...
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
error: Failed to merge in the changes.
Patch failed at 0001 update file in bugfix branch
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort"

此时我们进入了一个临时分支。

2、查看冲突
git status,提示test.txt文件冲突。
打开test.txt,可以看到如下冲突:

1
2
3
4
5
<<<<<<< HEAD
hello master
=======
hello bugfix
>>>>>>> update file in bugfix branch

3、解决冲突
修改test.txt如下:

1
hello master bugfix

4、提交

1
2
git add test.txt
git rebase --continue

5、查看提交记录

1
git log

可以看到三条记录:

1
2
3
update file in bugfix branch
update file in master branch
first commit

5.4.2. rebase保留master

需求:text.txt 打算保留master分支中的内容,舍弃bugfix分支中的内容。
text.txt最终内容为:

1
hello master

1、通过rebase命令合并master分支到bugfix

1
2
git checkout bugfix
git rebase master

提示冲突:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
First, rewinding head to replay your work on top of it...
Applying: update file in bugfix branch
Using index info to reconstruct a base tree...
M test.txt
Falling back to patching base and 3-way merge...
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
error: Failed to merge in the changes.
Patch failed at 0001 update file in bugfix branch
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort"

此时我们进入了一个临时分支。

2、查看冲突
git status,提示test.txt文件冲突。
打开test.txt,可以看到如下冲突:

1
2
3
4
5
<<<<<<< HEAD
hello master
=======
hello bugfix
>>>>>>> update file in bugfix branch

3、解决冲突
修改test.txt如下:

1
hello master

或者直接使用命令行解决冲突:

1
git checkout --ours test.txt

4、提交

1
2
git add test.txt
git rebase --skip

5、查看提交记录

1
git log

可以看到两条记录:

1
2
update file in master branch
first commit

5.4.3. 放弃rebase

rebase过程中,可以随时放弃rebase

1
git rebase --abort

5.5. 解决冲突小结

合并时难免代码冲突,git会将冲突的代码用 <<<<<<< HEAD ======= >>>>>>> xxx 标识出来,其中=======之前表示的是ours分支,之后表示theirs分支。

解决冲突办法:首先确定保留哪一部分代码,然后手动删除标志 <<<<<<< HEAD ======= >>>>>>> xxx,最后commit。

如果想要保留两个分支中的某一个,可以使用 git chekout --ours <fileName> 或者 git checkout --theirs <fileName>

对于merge和rebase来说,这两个选项对应的分支正好是相反的。
在使用 merge 时,ours指的是当前分支(master),theirs指的是要被合并的分支(dev)。
而在 rebase 时,theirs指的是当前分支(dev),ours指向(master)。

6. HEAD分支告警

6.1. 问题描述

执行 git status,出现了warning

1
warning: refname 'HEAD' is ambiguous.

6.2. 解决办法

解决办法:删除 HEAD 分支

1
git branch -D HEAD

原因分析:
这个问题是因为我们有一个叫做 HEAD 或者 head 的分支造成的,这个名字是一个保留字,它用于标示哪个分支是当前分支 ,而不应该直接拿来做分支的名字。
但是 remote 的 HEAD 分支是 OK 的,比如 origin/HEAD,经常有人把这个 checkout 下来,结果就变成了本地的 HEAD 分支,这就是此问题产生的源头。
如果用 HEAD 创建了一个 tag,这也会引起相同的问题。

参考文档:git warning: refname ‘HEAD’ is ambiguous是什么问题

  • 本文作者: 好好学习的郝
  • 原文链接: https://www.voidking.com/dev-git-branch/
  • 版权声明: 本文采用 BY-NC-SA 许可协议,转载请注明出处!源站会即时更新知识点并修正错误,欢迎访问~
  • 微信公众号同步更新,欢迎关注~