有没有一种简单的方法可以在git中压缩许多提交



我有以下问题:
我有很多提交需要压缩(几千个,我们有一个失控的脚本(。这些提交分为40到200组。
使用git rebase -i是不可行的,因为它会涉及太多的劳动力。我们有一个工具,可以从分支HEAD输出这样一个组相对的第一次和最后一次提交(可以通过其引用哈希来获得实际提交(。

因此,作为一个例子,我正在寻找一种可以在一次提交中压缩HEAD~400到HEAD~200的东西。然后可以再次运行(带有更改参数(,将HEAD~100到HEAD~50压缩到另一个提交中。

编辑1:
我曾考虑过创建一个"假的";编辑器,它通过对rebase文件执行更改来伪造交互性。一个抽象的示例脚本看起来是这样的(我可以循环它,直到所有的组都被压扁为止(:

start=$('get start of oldest group')
end=$('get end of oldest group')
git config core.editor "'~/fakeeditor' -start $start -end $end"
git rebase -i

我个人最喜欢使用git reset --soft

所以,假设你想从HEAD~1000压缩到这一点(HEAD~1000是最后一个幸存的提交,不会被压缩(:

git reset --soft HEAD~1000
git commit -m "Squashed a lot of stuff"

就是这样。您可以使用修订ID,而不是使用HEAD~n引用。

我看到你想像分段一样做。。。。所以,说。。。。让我们挤压头部~400到头部~200…然后从头部~200到头部~100…再从头部~100到头部。所以,让我们创建一个临时分支来完成我们的工作。

git checkout -b temp HEAD~200
git reset --soft HEAD~400
git commit -m "squashing first segment"
# next segment
git checkout the-original-branch~100
git reset --soft temp
git commit -m "Second segment"
git branch -f temp #set temp over here
# final segment
git checkout --detach the-original-branch
git reset --soft temp
git commit -m "Final segment"
git branch -f temp #set temp over here
# if you like the result, feel free to move whatever branch over here
git branch -f whatever-branch
# and delete temp if so you want
git branch -D temp

我觉得很简单。

一天后,我刚刚意识到(通过回答另一个问题(可以用一种简单得多的方法来完成:

git branch -f temp $( git commit-tree -p HEAD~400 -m "first squash" HEAD~200^{tree} )
# that set up temp on the first squash
git branch -f temp $( git commit-tree -p temp -m "second squash" HEAD~100^{tree} )
# temp has move to second squash
git branch -f temp $( git commit-tree -p temp -m "final squash" HEAD^{tree} )

现在,temp按照我的示例中请求的方式进行压缩提交。请随意在那里做一个reset --hard(使用reset --hard时的常见警告(。

首先,创建一个脚本来操作git-rebase:的todo列表

squash-it文件:

#!/bin/sh
first=$(git rev-parse --short "$1")
last=$(git rev-parse --short "$2")
todo="$3"
lines=$(
sed -n "/^pick $first /,/^pick $last/{s/^pick/squash/p}" "$todo" | sed "1s/squash/pick/"
sed "/^pick $first /,/^pick $last/d" "$todo"
)
echo "$lines" > "$todo"

然后像这样使用这个脚本:

GIT_SEQUENCE_EDITOR='sh -c "./squash-it HEAD~100 HEAD~50 $1"' GIT_EDITOR=cat git rebase -i HEAD~100^

如果您想要squash,可以将其替换为fixup

当然,您可以在脚本本身中生成这一行,例如,它将在循环中根据您的喜好替换HEAD~100HEAD~50

您可以提前为git rebase -i生成整个命令列表,然后将它们粘贴到编辑器中。这个过程看起来像这样:

  1. 对于要压缩的每一批提交,生成一个完整的提交哈希列表,前面是单词fixup;假设开始和结束提交在$start$end:git log "$start...$end" --pretty='fixup %h'
  2. 在每批提交之间,使用pick执行相同的操作;可以取一批南瓜的末尾和下一批南瓜开头的父级,然后丢弃第一行:git log "$end...$nextStart^" --pretty='pick %h' | sed -n '2,$p'
  3. 在要压缩的第一个提交之前找到提交,并以此为参数运行git rebase -i
  4. 删除git生成的所有行,并粘贴到准备好的待办事项列表中
  5. 保存并退出编辑器,git的rebase工具将处理您的列表

最新更新