Py学习  »  Git

重新排序git历史记录并保留内容,而不是提交/修补

SGKoishi • 3 年前 • 1361 次点击  

例如,有这样的git历史记录

root-commit 1 @ day 1
+ d1

commit 2 @ day 3
- d1
+ d3

commit 3 @ day 2
- d3
+ d2

第2天和第3天的两次提交出现问题,我想交换它们。 我希望结果是

root-commit 1 @ day 1
+ d1

commit 2 @ day 2
- d1
+ d2

commit 3 @ day 3
- d2
+ d3

历史是线性的,没有任何分支或合并。我试图使用rebase,但它似乎在操作现有的提交(补丁),我将放弃这些补丁,例如 - d1 + d3 犯罪由于冲突,重新定基将无法应用,需要手动解决,这对我来说是不可行的。

我能想到的方法就是 git archive (或 git diff 使用根提交)对所有提交进行排序,并创建一个全新的历史记录。有更好的方法吗?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/128087
 
1361 次点击  
文章 [ 1 ]  |  最新文章 3 年前
torek
Reply   •   1 楼
torek    3 年前

Rebase是一个错误的工具,但是Git并没有为你的工作提供正确的工具,因为这个工作。。。Git从来没有设计过这样的功能 .

不过,吉特 可以 去做吧。这只是使用底层组件的问题,而不是任何面向用户的顶级(“瓷器”)命令。

我可以想到的方法是对所有提交进行git归档(或git diff和根提交),对它们进行排序,并创建一个全新的历史记录。有更好的方法吗?

使用 git archive 会是 可以 ,但这项工作超出了需要。使用 git diff 每一次都会有更多的工作要做,而且不太合适。

最简单的方法是使用 git commit-tree .这是一个低级(“管道”)命令,需要三个输入:

  • 它需要一个 父哈希ID列表 。在父提交(单数)时,您将选择第一次提交的根提交,然后选择您刚刚为每个后续提交所做的最后一次提交。

  • 它需要一个(单一的) 树哈希ID 用于将源树存储在提交中。对于每一次新的提交,您都将选择与当天提交相关联的源代码树。

  • 最后,它需要一个 提交消息 .你可以把当天的承诺信息反馈给它。

您可能还希望覆盖提交人和提交人日期以及作者和作者日期的默认设置。你可以从四个到六个独立的环境变量, GIT_AUTHOR_NAME , GIT_AUTHOR_EMAIL , GIT_AUTHOR_DATE ,以及相应的三个变量 COMMITTER 代替 AUTHOR .或者,在tcsh/bash大括号扩展语法中, GIT_{AUTHOR,COMMITTER}_{NAME,EMAIL,DATE} .获取这些值的地方将是您转换的原始提交。

总体而言,您的脚本可能如下所示:

last=$root    # find and set the root commit hash ID

for commit in $(get-list-of-original-commits-to-copy-in-new-order); do
    set_author_and_committer $commit   # set-and-export GIT_{AUTHOR,COMMITTER}_*
    new=$(git log --no-walk --format=%B $commit |
          git commit-tree -p $last ${commit}^{tree})
    last=$new
done
git branch rewrite $last

(未经测试,需要编写一些函数)。这个 git log --no-walk --format=%B 提取表单中的原始提交消息 git提交树 需要,以及 git提交树 默认情况下从stdin读取提交消息,因此这里没有特殊工作。我们只是通过 -p 以及通过符号方法指定与被复制的提交相关联的树的树散列(参见 the gitrevisions documentation ).

用于设置和导出 GIT_* 变量可以在 the old git filter-branch script .

请注意,此脚本会破坏提交中的任何GPG签名;处理它们需要一些更高级的东西。