我如何简单地线性化我的git历史?

时间:2013-08-01 07:50:55

标签: git

问题

鉴于我有如下提交:

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 =我们合并为L,而P合并为M.

我希望能够将我的历史线性化,以便可以识别和检查这些有问题的提交。我希望有一个树可以识别O没有被放入上游分支,即使我可能通过使用git cherry识别上游分支中可能缺少N和P,但是这里的任何建议都将受到赞赏

2 个答案:

答案 0 :(得分:18)

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

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
    

答案 1 :(得分:5)

使用以下方法手动执行:

git rebase -i D-sha1

编辑文件以将G设置为“编辑”。保持并选择H.保存并关闭编辑器。

现在Git允许你编辑G commit,让我们将它修改为F commit的squash merge。你想要:

#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

请注意,如果必须在第一次合并中,则必须解决相同的冲突......

正如你所说,你只有G和H的新SHA1。