Git 合并简单与壁球。目的是什么?如何跟踪每个功能的一次提交?

Git Merge simple vs Squash. What is the purpose? How to track one commit per feature?

我不喜欢 Git 的一件事是提交的数量。不要误会我的意思,这是一种非常方便的(安全地)存储您的工作的方法,但是在很长的 运行 中,搜索的粒度太大了。

让我在使用从 develop.

分支的功能分支进行开发时描述以下场景

之所以有三个分支是因为有一个团队在处理存储库。 Feature3 假定 Feature1 已完成,等待合并到开发中。还有其他用例,但这是最简单的示例。

我的目标是在完成所有功能后在 develop 上提交三个。

使用gitmerge/pull

以上场景效果很好。因为本质上这两个命令都将提交移动到开发分支中。合并 Feature1 时,develop 引用它的五个提交。当 Feature3 将被合并时,只有最后两个提交会被合并到 develop.

唯一的负面影响是 develop 提交太多。这意味着当合并到 master 时,所有 "noise" 都会移动。所以我的目的没有达到。

使用 git 与 squash 合并

当合并 Feature1 时,develop 得到一个新的提交,它是所有 Feature1[=79 的聚合=].这非常好,因为现在只需一次提交即可跟踪该功能。当删除 Feature1 时,所有中间提交都不再可见,从而使跟踪更容易。这也与诸如一个拉取请求和一个 github 问题等概念相匹配。

Feature3 将要合并时,出现冲突并出现问题。要解决这个问题,您需要将 develop 合并回 feature3。与冲突。这会导致一个新的提交,其中有零个文件被更改。现在我们将 squash Feature3 合并到 develop.

我的目标实现了,但在微观管理上做出了很多牺牲。

Questions/Remarks

据我了解,这就是 git 现实。我读过的一个建议是创建一个兄弟功能分支来保存压缩的合并提交。将兄弟分支用于拉取请求,因此强制每个功能使用一个提交。这并不能解决在尝试合并其他分支时产生的冲突,尤其是从其他功能分支继承的冲突。

  • 能否在同一分支内进行内部压缩?我不这么认为,但问问也无妨。
  • 我是不是漏了什么?
  • 这是挤压合并的权衡吗?解决可能具有零代码更改的冲突?
  • 追求"one commit per feature"概念是否值得?
    • 如果不是,那么 squash 的目的是什么?谁在使用这个?

我已经阅读了使用 rebase 的替代方案并在合并后使用 reset 模拟壁球,但​​据我了解 none 解决了提到的合并 feature3 的开销。

我真的认为变基是你的解决方案。

如果我理解,下面是你的git结构:

develop \ A - B - C [feature1] \ D - E [feature3]

你的问题是,一旦你将 feature1 压缩并合并到 develop,最初的三个提交 feature3 引用不再存在。你本质上就像下面这样,除了 feature1 并不真正存在。

develop — feature1Merge \ A - B - C [feature1] \ D - E [feature3]

因此 feature1Mergedevelop 中的提交与 feature3 的历史记录不同.

在这种情况下,如果您尝试 rebase feature3 回到 develop,提交 A BC 会随之而来,理论上这不会导致任何问题,因为更改已经在 develop 上,所以 git 应该只是 fast-forward 那些提交。显然,这似乎并没有发生。

在这种情况下我建议做的是rebase onto

变基到

--onto 选项允许您变基特定的提交,而不是整个分支。

因此,为了停止 git 尝试在变基时使用提交 A BC,我们使用 --onto,它有 3 个参数:

  • 分公司新基地

  • 分支当前基地

  • 要变基的分支名称

在你的情况下,这将是:

git rebase --onto develop C feature3

这将检查 develop,然后应用 feature3C:

以来的所有提交

develop — feature1Merge \ D - E [feature3]

希望这一切都有意义,并尽可能少地实现您想要的!

是的,git 有这么多提交的目的是让每个更改都可跟踪。如果某些提交并不重要,或者可以将所有更改记录在一个提交中供您查看历史记录,那么您当然可以压缩这些提交。

针对您的问题:

1.Yes,你可以做一个内部壁球。假设您的 git 提交历史如下图所示:

                K---L---M        Feature2
              /
A---B---…---C---…                develop
     \         
      D---E---F---G---H          Feature1
                        \
                          I---J  Feature3

您可以使用这些步骤来压缩每个分支:

git checkout Feature1
git rebase -i HEAD~5

输入i

pick D
squash E
squash F
squash G
squash H

press Esc button and then input :wq

git checkout Feature3
git rebase -i HEAD~7
pick D
squash E
squash F
squash G
squash H
squash I
squash J
git rebase Feature1
git checkout Feature2
git rebase -i HEAD~3
pick K
squash L
squash M
  1. 你的流程没问题。
  2. 要压缩提交,第一个(最旧的)应该使用 pick,其他人可以使用压缩,这样它会显示只有一个提交的分支。如果有冲突,可以修改并保存冲突文件,然后使用git add .git rebase --continue.
  3. 不一定,看你喜欢。 squash 的主要目的是让历史看起来更整洁和清晰。