我正在将旧的SVN存储库转换为Git,其中包括尝试在所有正确的位置获取所有分支/标记。那部分进展顺利,但有时候我想在我的脚本中添加历史记录中的提交,后来我想用下一次提交压缩。问题是我不是一个接一个地抓取提交,而是作为一个大的组,因此当我将它们从SVN存储库中拉出时,我无法压缩它们。最后,我的存储库看起来像这样:
* (branch_2, HEAD) commit 5
* commit 4
* commit 3
* SQUASH ME!
* (branch_1) commit 2
* commit 1
我希望能够用commit 3
压缩SQUASH ME!
,这显然很容易使用交互式rebase,但在脚本中更具挑战性。我似乎遇到的主要问题是虽然很容易签出branch_1
或之前的任何提交,但很难以编程方式在之后请求提交并且我很难预测如何我需要从branch_2
返回许多提交内容。我真的希望能够做到这样的事情:
git checkout branch_1+2
任何指针?
答案 0 :(得分:7)
你所说的不是壁球,而是 fixup ,因为壁球会以交互方式询问你提交msg,而修正使用来自HEAD提交的提交消息。
这是一个没有干预的脚本。
脚本:/usr/bin/git-fixup
#/bin/bash
# This command fixesup one commit onto his parent
set -e
# We need a commit from the first argument of that command
commit=${1:?No commit given as first argument}
startingbranch=$(git rev-parse --abbrev-ref HEAD)
# Checkout the parent of the asked commit
git checkout "$commit"
git checkout HEAD~
# Merge the commit into it's parent, keeping the commit message of the parent
git merge --squash "$commit"
git add .
git add --update
git commit --amend --no-edit
# Store the current commit
newcommit=$(git rev-parse HEAD)
# Rebase the starting branch onto the new commit
git checkout "$startingbranch"
git rebase "$newcommit"
与
一起使用git fixup <commit-id>
例如,如果您的历史记录是:
ce0e2fd (master, HEAD) commit 4
72ab3c4 commit 3
8150939 commit 2
301c1e1 commit 1
你可以git fixup 72ab3c4
合并在一起&#34;提交3&#34;并且&#34;提交2&#34;作为提交消息&#34; commit 2&#34;,并将您放回主分支。
答案 1 :(得分:5)
来自git rebase --help
:
<强> - autosquash 强>
当提交日志消息以&#34; squash开头时! ...&#34; (或&#34; fixup!...&#34;),并且有一个提交,其标题以相同的开头 ...,自动修改rebase -i的待办事项列表 因此,标记为压缩的提交在修改提交之后立即生效,并更改已移动提交的操作 从挑选到壁球(或修复)。
此选项仅在使用--interactive选项时有效。
如果输入的格式正确,那看起来它会做你想要的一半。
另一半阻止它启动交互式编辑器。幸运的是,编辑器是可配置的,所以我们可以将其设置为无害的。
试试这个:
env EDITOR=true git rebase -i --autosquash <from-here>
将编辑器设置为true
(一个只是成功退出的工具)足以说服git继续使用默认的rebase设置,自动壁球应该设置为有用的东西。
或者,如果--autosquash
没有做您想做的事情,您可以将EDITOR
设置为您喜欢的任何脚本:
env EDITOR=mysquasher.sh git rebase -i <from-here>
脚本可以执行您需要的任何操作,但在您的情况下,只需查找包含"SQUASHME!"
的每一行,并更改以下行中的"pick"
以阅读"fixup"
。使用awk可能最容易实现这一点:
#!/bin/bash -e
awk -- 'BEGIN {dosquash=0}
dosquash==1 {gsub(/^pick/, "fixup"); dosquash=0}
/SQUASHME/ {dosquash=1}
{print}' "$1" > /tmp/tmp.$$
mv /tmp/tmp.$$ "$1"