gpt4 book ai didi

git - 如何压缩分支中的提交

转载 作者:太空狗 更新时间:2023-10-29 14:11:22 25 4
gpt4 key购买 nike

我正在将一个旧的 svn 存储库导入到 git 中。有一次,一个文件夹在所有分支中都被重命名了。这是在 svn 中通过创建具有历史记录的副本来完成的,然后在第二次提交时删除原始文件。所以我有一个看起来像这样的 repo 协议(protocol):

A -> B -> C -> D* -> E* -> F -> G -> H
\-> 1 -> 2* -> 3* - > 4 -/

D/E 和 2/3 是我要压缩的提交。压缩的原因是虽然 svn 知道“与历史重复”,但 git 不认为这是重命名,因为原始文件直到下一次提交才被删除,我在这一点上失去了历史。

我已经尝试了一些可行的 rebase 脚本,但它们也压平了我的所有分支。以上是我必须做的事情的一个非常简化的版本,这就是为什么我真的需要脚本,因为我不能手动完成。在整个 SVN 存储库的历史中,有超过 1,000 个分支,并且可能有十几个并行分支完成了此更改(全部同时进行)。

git repo 尚未发布,因此维护哈希无关紧要。我假设我需要使用一些过滤器分支脚本,但我仍在尝试弄清楚如何管理我希望能在这里得到帮助的东西。我可以提供每个需要压缩的提交及其父提交的 sha1。

最佳答案

您想使用 git filter-branch 使用 --parent-filterD 的 SHA 的任何外观替换为 C 的 SHA。您还可以查看 .git/info/graftsgit replace ,这可能比编写 --parent-filter 更简单,并且可以使用 filter-branch 使其永久化。

更新:正如@torek 所说,你绝对应该使用 git replace .举一个真实的例子,这里是从 readme.mdREADME.md 的重命名,中间重命名为 README1.md : https://github.com/dahlbyk/posh-git/compare/dahlbyk:2b9342c...dahlbyk:57394c5 .我们将 2b9342c 称为 C 并将 57394c5 称为 E:

$ git tag E 57394c5
$ git tag C 2b9342c
$ git tag G 450d8f1
$ git log --oneline --graph --decorate C~..G
* 450d8f1 (tag: G) Merge pull request #320 ...
|\
| * 941935c Fix a few kbd / missing markdown issues/
| * f13dcf9 Upcase readme and have more prompt examples.
| * 57394c5 (tag: E) Now rename to README.md.
| * eb79ef2 Prepare to upcase README.md filename.
* | 536c57f Merge pull request #319 ...
|\ \
| |/
|/|
| * 7fafb7b Speed up Get-GitStatus
|/
* 2b9342c (tag: C) Merge pull request #313 ...

为了假装中间移动从未发生过,我可以替换 E 的父级 (E~) 为其祖父级 (E~2 = C):

$ git log --stat --oneline C..E
57394c5 Now rename to README.md.
README1.md => README.md | 0
1 file changed, 0 insertions(+), 0 deletions(-)
eb79ef2 Prepare to upcase README.md filename.
readme.md => README1.md | 0
1 file changed, 0 insertions(+), 0 deletions(-)
$ git replace E~ C
$ git log --stat --oneline C..E
57394c5 Now rename to README.md.
readme.md => README.md | 0
1 file changed, 0 insertions(+), 0 deletions(-)
eb79ef2 Merge pull request ...

最后,filter-branch 将使更改永久化:

$ git filter-branch -- ^C G E  # For demo, only rewrite G & E afer C
$ git log --graph --oneline --decorate C~..G
* fcfd345 (tag: G) Merge pull request #320 ...
|\
| * fa76267 Fix a few kbd / missing markdown issues/
| * 4900687 Upcase readme and have more prompt examples.
| * b25aa5a (tag: E) Now rename to README.md.
* | 536c57f Merge pull request #319 ...
|\ \
| |/
|/|
| * 7fafb7b Speed up Get-GitStatus
|/
* 2b9342c (tag: C) Merge pull request #313 ...

为了您的目的,您将执行如下操作:

$ git replace E~ E~2
$ git replace 3~ 3~2
$ git filter-branch -- ^A --all

更新 2:

The commit message I get is off of E, which I don't care about. I'd rather have D's commit message (or a script provided message).

为了保留 D 的提交元数据,我建议重新开始并使用 --commit-filter 来指定 Etree (git cat-file -p E) 用于 D(并且 E 应该被跳过),例如

git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = "SHA of D" ];
then
git commit-tree "TREE of E" -p "SHA of C";
elif [ "$GIT_COMMIT" = "SHA of E" ];
then
skip_commit "$@";
else
git commit-tree "$@";
fi;
' -- ^A E G

关于git - 如何压缩分支中的提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42399149/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com