Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我如何简单地线性化我的git历史? 问题:_Git - Fatal编程技术网

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

我如何简单地线性化我的git历史? 问题:,git,Git,考虑到我有一个如下所示的提交: A - B - C - D - G - H \ / - E - F - git rebase -i D-sha1 我怎样才能得到一个完全线性的历史记录,只跟随第一个父母 例如,我想得到: A - B - C - D - G'- H' 如上所述,预计G和H的sha1将发生变化。(由于明显的原因)。如果A、B、C和D的sha1也改变了,那么我想知道为什么 背景 这样做的目的是避免在执行简单的git rebase-i时可能出现

考虑到我有一个如下所示的提交:

A - B - C - D - G - H
     \         /
      - E - F -
git rebase -i D-sha1
我怎样才能得到一个完全线性的历史记录,只跟随第一个父母

例如,我想得到:

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合并到L中,p合并到M中


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

使用以下方法手动执行此操作:

A - B - C - D - G - H
     \         /
      - E - F -
git rebase -i D-sha1
编辑文件,使G设置为“编辑”。为H保留“拾取”。保存并关闭编辑器

现在Git允许您编辑G提交,让我们将其修改为F提交的挤压合并。您想:

#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。

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

git filter-branch --parent-filter 'cut -f 2,3 -d " "'
为什么?

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

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

带有
--parent filter
选项的
git filter branch
命令允许重写每个提交的父级,作为
-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
    

如何识别“G”和“H”?假设我有一个大型存储库,。不仅仅是我强调的那个小案例,还有很多这样的合并提交。如果历史太复杂,不同的合并提交无法线性化,那么您可能会远离这个。Git rebase做不到我完全知道Git rebase做不到。我希望答案将涉及git filter branch和--parent filter集合。即使使用
filter branch
,您仍然必须确定筛选或重定基址的“起点”。我建议编写一个脚本,使用
git rev list--merges
查找合并提交。我从来没有这样做过,所以我不太确定如何从这一点出发,虽然。对我来说也是一样,可能是可行的,但如果有人这样做,它将成为一篇很好的文章/博客文章!为了重新表述您的问题,您希望修改每个合并提交以仅保留其第一个父级,忘记合并的分支(当然保留差异)@CharlesB:Yep,没错!这启发了我去尝试:
git filter branch——父过滤器‘cut-f2,3-d’
它似乎可以工作,但我还不能确定边缘情况或性能。不过,我确实有数百个相当大的提交。我会等待你的回答,你可能会有更好的解决方案。我不知道,但看起来简单多了。我想在这种脚本中使用
--commit-filter
,但我也看到了
--parent-filter
选项,尽管我不明白命令中的
cut-f 2,3
是什么?parent-filter指定了一个程序,该程序需要在stdin上输入,比如“-p sha1-p sha1-p sha1”,每个-p指定一个父级。(该字符串包含三个父级的合并提交)。其中的'-d''指定我们将其解释为一个列表,由空格分隔-f中指定了“获取第二项和第三项”。这将生成第一个“-p sha1”,我们就完成了。不过,这“---all”对我来说没有意义。我只想在我当前的分支上执行。