24

问题

鉴于我有如下提交:

A - B - C - D - G - H
     \         /
      - E - F -

我如何仅在第一父母之后获得完美的线性历史?

例如,我想得到:

A - B - C - D - G'- H'

如上所述,预计 G 和 H 的 sha1 会发生变化。(出于显而易见的原因)。如果 A、B、C 和 D 的 sha1 也发生了变化,那么我想知道为什么。

背景

目的是避免在执行天真的 git rebase -i 时可能出现的潜在合并提交。

真正的重点是希望获得额外的洞察力,以确定哪些提交在特定的分支中,例如,如果我们有以下图表:

I - J - K - L - M
 \     /   /   / 
  - N - O - P -

其中 N 合并到 K 中,但 O 与 --strategy=ours 合并到 L 中,P 合并到 M 中。

我希望能够线性化我的历史记录,以便可以识别和检查此类有问题的提交。我想要一棵树,可以识别 O 没有放入上游分支,即使我可能通过使用 git cherry 将 N 和 P 识别为上游分支中可能丢失,但是这里的任何建议都将不胜感激.

4

2 回答 2

20

如您所说,以下命令有效:

git filter-branch --parent-filter 'cut -f 2,3 -d " "'

为什么?

您提出的问题通过使用简单提交转换每个合并提交来解决:这将简单地删除已合并的功能分支,因为它们将成为孤立的。

每个提交都有一个或多个父提交。合并提交是获得多个的提交。Git 将其存储在历史的每个提交对象中。

git filter-branch命令带有--parent-filter选项,允许重写每个提交的父级,传递给过滤器-p SHA1,如果有多个父级,则重复。我们的过滤器切断父节点并强制每个提交都有一个父节点。

作为奖励,这里是如何通过重新创建一个新的提交来手动执行精确的提交:

  • 获取提交树和第一个父级

    tree=`git show -s --format=%T SHA1`
    parent=`git show -s --format=%P SHA1 | cut -d " " -f1`
    
  • 使用相同的树、相同的消息进行新的提交,并且只保留第一个父级作为祖先

    git show -s --format=%B SHA1 | git commit-tree $tree -p $parent
    
于 2013-08-01T12:48:07.210 回答
5

Do it manually with the following:

git rebase -i D-sha1

Edit the file to have G set to "edit". Keep "pick" for H. Save and close editor.

Now Git lets you edit G commit, let's modify it to a squash merge of the F commit. You want to:

#cancel the merge commit and position HEAD to D
git reset --hard HEAD~
#squash merge and continue
git merge --squash F-sha1
git rebase --continue

Note that you'll have to solve the same conflicts if you had to in the first merge...

As you say you'll only have new SHA1 for G and H.

于 2013-08-01T08:05:32.327 回答