使用 Git 进行分支管理时,分支结构大概类似于这样:

main 是本地分支,origin/main 本地关联了目标服务器 origin 上 main 分支的分支。
一般来说,远程服务器会默认命名为 origin,当然也可以修改。
这里的每个圆形表示一次代码提交,每个提交都指向一个父提交。
从远程仓库更新代码
很常见的是,远程分支被其他人提交了代码:

此时需要使用fetch命令将最新的代码拉取到本地的远程分支:
git checkout main
git fetch
这样本地的origin/main分支的代码就是最新的了,可以切换到该分支查看日志进行确认:
git checkout origin/main
git log
现在是这样:

应当注意到,虽然本地的远程分支origin/main的代码更新了,但我们操作的本地分支main并没有更新,这是有意义的,有时候你不希望代码拉取后影响到本地分支。
如果你需要本地分支main也获取到最新的代码变更,就需要合并两个分支:
git checkout main
git merge origin/main
除了合并(merge)外,还可以基变(rebase)。
现在变成了这样:

这种操作很常见:
-
从远程服务器拉取代码(fetch)变更到本地的远程分支(origin/main)
-
合并本地的远程分支(origin/main)到本地分支(main)
因此如果你要进行类似的操作,可以使用更方便的 Git 命令:
git pull
如果你希望拉取后通过基变而非合并的方式将最新变更整合进本地分支,可以使用
git pull --rebase。
以上是一般性的从远程拉取代码的过程,实际上 Git 可以更灵活地将远程代码拉取到本地,而不需要通过本地远程分支(比如 origin/main)。
比如直接从远程服务器拉取main分支的最新代码到本地的一个新分支:
git fetch origin main:hot_fix/fix_demo
这会创建一个新分支:
❯ git branch -a
dev
hot_fix/fake_main_commit
hot_fix/fix_demo
* main
remotes/origin/dev
remotes/origin/main
甚至可以更灵活,比如从远程服务器的提交记录上找一个之前的提交记录,然后用该提交记录创建本地分支:
git fetch origin 32722ea488c88478986aab8c1fda2e725a100631:init
这里的
32722ea488c88478986aab8c1fda2e725a100631是 Git 提交记录的 hash 值。
新创建的本地分支将包含该提交以及其之前的提交记录。这里远程服务器标识origin后面跟的是<source>:<target>,source是远程仓库上的分支名称或者某个提交记录的 hash 值,target是本地分支名称。
提交代码到远程仓库
如果本地有代码变更,需要先添加到暂存区:
git add .
可以通过status查看添加到暂存区的文件状态:
git status
如果有问题,需要从暂存区撤销,可以:
git reset HEAD
这里撤销了所有暂存区文件,也可以指定文件以撤销具体文件。
添加到暂存区的文件最终需要提交到本地分支:
git commit -m 'add test2 function'
该操作会将暂存区的文件作为一个提交添加到 HEAD 关联的本地分支。

最后,我们还需要将本地分支的修改推送到远程分支:
git push

这个操作会将本地分支修改提交到远程分支,并通过fetch操作将变更后的远程分支更新到本地的远程分支origin/main。
撤销提交
如果我们要撤销的提交仅仅发生在本地分支,还没有推送到远程分支:

可以:
git reset HEAD~1
HEAD~1表示的是将 HEAD 向上移动一位,换言之就是撤销最近一次提交。

但如果修改已经提交到远程分支,这样做是没有效果的,因为一旦后续执行了从远程分支更新代码的操作,撤销的代码就会重新出现。

此时就需要使用revert命令执行撤销操作:
git revert HEAD
这个操作会在本地分支添加一个用于执行撤销(revert)的提交,我们需要将这个提交推送到远程分支:
git push

合并代码
一般性的代码合并是这样的:

如果在feature/2分支上合并feature/1分支:
git checkout feature/2
git merge feature/1

feature/2分支会出现两个新的提交记录,一个是从feature/1分支合并赖的,另一个是用于合并的提交记录。
这样合并本身并没有问题,且提交之间的关联关系很明确,但实际操作会有一些麻烦,比如如果我们要撤销提交记录:
git revert HEAD~
撤销提交 5 很容易,但撤销后的 HEAD 要指向 3 还是 4?
此时 Git 会要求我们指定一个父提交(parent)。
因此,除了这种默认的合并方式,Git 还支持另一种合并方式:变基(rebase)。
git rebase feature/1
如果变基时产生冲突,需要解决冲突后再执行
git rebase --continue继续执行变基。
通过变基合并的代码提交记录是线性的:

cherry-pick
一般来说,Git 更建议尽可能创建多的分支,针对分支进行合并,但也支持针对具体的提交记录进行更灵活的分支操作。
比如开发分支上有多个提交记录:

假设现在要将其中的 3 和 5合并到主分支进行发布,我们可以先创建一个预发布分支:
git checkout main
git branch release/260126
git checkout release/260126
git push -u origin release/260126
查看当前位于 dev 分支,但没有合并到 main 分支的提交记录:
❯ git log --oneline main..dev
e76a0e0 (origin/dev, dev) commit 3
fe38633 commit 2
50cb6a1 commit 1
将其中两个拣选(cherry-pick)到预发布分支:
git checkout release/260126
git cherry-pick e76a0e0 50cb6a1
git push
注意,
cherry-pick后的提交记录顺序就是添加到分支中的顺序。

基于预发布分支进行测试,测试通过后将预发布分支和主分支进行合并:
git checkout main
git rebase release/260126
git push

主分支发布后,预发布分支可以删除:
git branch -d release/260126
git push origin --delete release/260126
The End.

文章评论