13

尽管 Git 是一个非常强大的工具,但是我相信大部分同学有时候学起 Git 来,感觉很难搞~ 笔者总是习惯于在脑海中重现学习的知识,Git 也一样:当我们执行了切换分支命令,分支之间是如何交互的?又是如何影响历史提交的?当我在 master 分支上执行了强制 resetforce push 到了远端 ,又把 .git 文件夹删掉,我的同事为什么会哭??

于是就有了将这些命令做成动画的想法!由于篇幅有限,本文主要覆盖一些常用命令的默认行为~

Merge Rebase Reset Revert Cherry-Pick Fetch Pull Reflog

合并(Merging)

使用多个分支可以方便我们隔离彼此,也可以防止意外提交到生产环境,对分支模型感兴趣的小伙伴也可以看笔者之前的文章:

使用 git-flow 自动化你的 git 工作流

当我们的某个功能开发完成时,就需要将这些更改应用到生产环境上。其中一个应用的方式就是 git merge !而这个命令有两种类型:一种叫 fast-forward 方式,一种叫 no-fast-forward 方式。

现在不太懂没关系,我们先来对比下这两个选项。

以下例子中将 master 称作 主分支当前分支

Fast-forward (--ff)

一个 fast-forward merge 可以被用于:当 主分支 相比 要被合并的分支 没有额外的提交时。Git 是。。懒惰的,它会首先尝试使用这个最简单的 fast-forward 选项。这种方式不会创建新的 commit,可以说它只是把我们的提交和 HEAD 指针挪了一个位置。

1-merge-ff.gif

完美!现在我们所有的更改都从 dev 分支合并到 master 分支了~

No-fast-forward (--no-ff)

主分支没有额外的提交当然是最好的情况,但是在多人协作的情况下,这种情况当然就很少见了,毕竟大家都在加班嘛~ 那么如果主分支具有额外的提交时,在 merge 时,git 就会使用 no-fast-forward 选项。

在使用 no-fast-forward 选项时,Git 就在当前分支创建了一个新的 合并提交。而这个提交的上一级同时指向了当分支和要合并的分支!具体见动图:

1-merge-no-ff.gif

没啥大不了的,完美合并!现在 master 分支就包含 dev 分支中的所有提交了。

合并冲突(Merge Conflicts)

尽管 Git 对于合并的默认行为非常棒,但是总有需要我们自己解决的时候。比如说,当两个分支上都有新的提交,又同时修改了同一个文件同一行的内容,或者一个分支上删除了一个文件,而另一个分支却修改了那个文件等等。

这些情况下,Git 就会请我们来帮忙啦。假设我们在两个分支上同时修改了 README.md 文件。

2-conflicts.png

如果我们想要将 dev 合并到 master,这就会产生一个冲突(conflict):因为 Git 也不清楚你到底是想要 Hello! 还是 Hey!

所以当我们合并分支时,Git 会告诉我们冲突发生的具体位置。我们需要手动删除不要的地方,保存更改,然后再提交。

2-conflicts-ani.gif

赞!尽管造成冲突非常烦人,但也符合逻辑,机器毕竟是机器,它肯定不能替我们决定需要保留哪块内容吧~

变基(Rebasing)

刚刚我们见识了 git merge 的合并过程。另一种将变更从一个分支应用到另一个分支的方式是:git rebase

关于这两个命令的区别也可以看笔者之前的文章:

带你理解 Git 中的 Merge 和 Rebase

简单来说就是:Merge 保留历史记录,而 Rebase 改写历史记录

git rebase 将提交从一个分支(dev)复制到另一个分支(master)的顶部。

3-rebase.gif

完美,现在我们已经将 dev 的起点设置为新的 master 分支了。

相比 Merge 来说一个很大的不同点是,Git 不会去查找哪个文件需要保留,哪个不需要。我们的 dev 分支可以使用 rebase 来一直追踪最新的 master 分支。这样就不会产生冲突,同时也会有一个线性的 Git 历史记录。

图中的例子是将 master 作为 devbase (基础分支), 在大型项目中,通常我们不会这么做。git rebase 会修改项目的历史记录,同时复制的 commit 也会生成新的 hash 值。

当你在 feature 分支上工作,而 master 分支又更新了,这时就可以使用 rebase,无缝地将 master 上的分支更新到你的 feature 分支了!

交互式变基(Interactive Rebase)

在进行变基之前,我们也可以修改之前的提交,这就用到了 交互式变基。交互式变基也适用于你想要修改当前工作分支的某些提交。

一共有 6 种操作可以应用到之前的提交上:

  • reword:修改提交的信息 (commit message)
  • edit:修改提交内容
  • squash: 将某个提交与前一个提交合并
  • fixup: 同 squash,但是丢弃提交信息
  • exec:在想要 rebase 的提交上依次执行某个命令
  • drop: 删除某个提交

好啦!这样,我们就可以完全掌控我们的提交。如果你需要删除某个提交,只需要 drop 就好~

3-rebase-2.gif

或者说如果我们为了干净的历史记录,需要合并多个提交,也没问题:

3-rebase-3.gif

交互式变基给了我们很大的权力来控制提交,即使在你当前工作的分支也没问题。

未完待续

好啦,由于原文篇幅太长,本篇我们先讲了前两个命令:MergeRebase,这两个同时也是 Git 分支操作中最重要的两个命令,下一篇我们继续讲剩下的六个命令~

关注我了解更多哦~

参考文章


本文首发于公众号:码力全开(codingonfire)

本文随意转载哈,注明原文链接即可,公号文章转载联系我开白名单就好~

codingonfire.jpg


savokiss
6.2k 声望4.5k 粉丝

You know nothing, SpongeBob.