如何使用一行压缩 git 中的两个非连续提交?
How do I squash two non-consecutive commits in git, using one line?
我知道我可以使用 rebase -i
来做到这一点,但我真的在寻找一种在一行中完成它的方法,例如,使用脚本。
例如我看了看How do I run git rebase --interactive in non-interactive manner?,但是我的bashfu太弱了,无法正常使用。
明确地说,这是我现在拥有的:
A1B2C3 一些承诺
AAAAAA 其他一些提交
A3B2C1 更多承诺
BBBBBB 另一个提交
我想在一行(或多行)git 行中以非交互方式压缩 AAAAAA 和 BBBBBB。
谢谢
您可以通过一系列精选和修改后的提交来模拟变基交互:
git checkout AAAAAA
git cherry-pick BBBBBB -n && git commit --amend -m "AAAAA squashed with BBBBB"
git cherry-pick A3B2C1
我最终在链接问题的帮助下使用了 bash 脚本。
为了完整起见,我附上了它。
注:我的bash是丑。
但有一点很重要:由于脚本不能接受参数,我选择了自修改代码。
如果有更好的解决方案(不使用 globals/environment 变量),我很想知道。
另外,我不完全确定如何交换 bash 中的两行(google 不是很好的帮助),所以我最终使用了 for
循环。
#!/bin/bash
commit1=???
commit2=???
if [ "$#" -eq 2 ]; then #2 arguments, first phase of script
#modify lines 2 and 3 with arguments
currentFile=${BASH_SOURCE[0]}
cat $currentFile | sed "2s/.*/commit1=/" | sed "3s/.*/commit2=/" >| $currentFile
echo "$currentFile"
exit
fi
# second phase of script
line1=$(grep -nr "pick $commit1" | cut -f1 -d:)
if [ -z $line1 ]; then
echo "Could not find a match for $commit1"
exit
fi
line2=$(grep -nr "pick $commit2" | cut -f1 -d:)
if [ -z $line2 ]; then
echo "Could not find a match for $commit2"
exit
fi
oldLine=$(($line1<$line2?$line1:$line2))
newLine=$(($line1>$line2?$line1:$line2))
cat
#move newLine to be below oldLine, by iterating over all lines in reverse and swapping one by one
for currentLineIndex in `seq $newLine -1 $(expr $oldLine + 2)`; do
currentLine=$(sed -n "${currentLineIndex}p" "")
nextLineIndex=$(expr $currentLineIndex - 1)
nextLine=$(sed -n "${nextLineIndex}p" "")
cat | sed $currentLineIndex"s/.*/$nextLine/" | sed $nextLineIndex"s/.*/$currentLine/" >|
done
#change the pick to squash
cat | sed $(expr $oldLine + 1)"s/pick/squash/" >|
使用示例:$ GIT_SEQUENCE_EDITOR=$(./rebase.sh d199 a548) git rebase -i 95e2a7c
一个更简单的选择,如果你只想修复暂存区的现有提交:(感谢@Andrew C 将我指向 --fixup
)
function git_fix {
git commit --fixup=
GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "^" #empty script
}
作为 git 别名:
fix="!f() {\
git commit --fixup=;\
GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "^";\
}; f"
我知道我可以使用 rebase -i
来做到这一点,但我真的在寻找一种在一行中完成它的方法,例如,使用脚本。
例如我看了看How do I run git rebase --interactive in non-interactive manner?,但是我的bashfu太弱了,无法正常使用。
明确地说,这是我现在拥有的:
A1B2C3 一些承诺 AAAAAA 其他一些提交 A3B2C1 更多承诺 BBBBBB 另一个提交
我想在一行(或多行)git 行中以非交互方式压缩 AAAAAA 和 BBBBBB。
谢谢
您可以通过一系列精选和修改后的提交来模拟变基交互:
git checkout AAAAAA
git cherry-pick BBBBBB -n && git commit --amend -m "AAAAA squashed with BBBBB"
git cherry-pick A3B2C1
我最终在链接问题的帮助下使用了 bash 脚本。
为了完整起见,我附上了它。
注:我的bash是丑。
但有一点很重要:由于脚本不能接受参数,我选择了自修改代码。
如果有更好的解决方案(不使用 globals/environment 变量),我很想知道。
另外,我不完全确定如何交换 bash 中的两行(google 不是很好的帮助),所以我最终使用了 for
循环。
#!/bin/bash
commit1=???
commit2=???
if [ "$#" -eq 2 ]; then #2 arguments, first phase of script
#modify lines 2 and 3 with arguments
currentFile=${BASH_SOURCE[0]}
cat $currentFile | sed "2s/.*/commit1=/" | sed "3s/.*/commit2=/" >| $currentFile
echo "$currentFile"
exit
fi
# second phase of script
line1=$(grep -nr "pick $commit1" | cut -f1 -d:)
if [ -z $line1 ]; then
echo "Could not find a match for $commit1"
exit
fi
line2=$(grep -nr "pick $commit2" | cut -f1 -d:)
if [ -z $line2 ]; then
echo "Could not find a match for $commit2"
exit
fi
oldLine=$(($line1<$line2?$line1:$line2))
newLine=$(($line1>$line2?$line1:$line2))
cat
#move newLine to be below oldLine, by iterating over all lines in reverse and swapping one by one
for currentLineIndex in `seq $newLine -1 $(expr $oldLine + 2)`; do
currentLine=$(sed -n "${currentLineIndex}p" "")
nextLineIndex=$(expr $currentLineIndex - 1)
nextLine=$(sed -n "${nextLineIndex}p" "")
cat | sed $currentLineIndex"s/.*/$nextLine/" | sed $nextLineIndex"s/.*/$currentLine/" >|
done
#change the pick to squash
cat | sed $(expr $oldLine + 1)"s/pick/squash/" >|
使用示例:$ GIT_SEQUENCE_EDITOR=$(./rebase.sh d199 a548) git rebase -i 95e2a7c
一个更简单的选择,如果你只想修复暂存区的现有提交:(感谢@Andrew C 将我指向 --fixup
)
function git_fix {
git commit --fixup=
GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "^" #empty script
}
作为 git 别名:
fix="!f() {\
git commit --fixup=;\
GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "^";\
}; f"