如何使用一行压缩git中的两个非连续提交?

时间:2015-02-19 13:03:13

标签: git bash

我知道我可以使用rebase -i执行此操作,但我真的想找到一种方法,例如使用脚本。 例如,我看了How do I run git rebase --interactive in non-interactive manner?,但是我的bashfu太弱而无法正常使用它。

要清楚,这就是我现在所拥有的:

A1B2C3 Some commit
AAAAAA Some other commit
A3B2C1 More commit
BBBBBB Another commit

我想以非交互方式将AAAAAA和BBBBBB压缩成一个(或几个)git行。

由于

3 个答案:

答案 0 :(得分:0)

你可以通过一系列的挑选和修改提交来模仿rebase交互:

git checkout AAAAAA
git cherry-pick BBBBBB -n && git commit --amend -m "AAAAA squashed with BBBBB"
git cherry-pick A3B2C1

答案 1 :(得分:0)

我最终在链接问题的帮助下使用了bash脚本。 为了完整起见,我附上它。 注意:我的bash是丑陋。 但有一点很重要:由于脚本不能接受参数,我选择了自修改代码。 如果有更好的解决方案(不使用全局变量/环境变量),我很想知道。 另外,我不完全确定如何在bash中交换两行(并且谷歌不是一个很好的帮助),所以我最终使用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=$1/" | sed "3s/.*/commit2=$2/" >| $currentFile
    echo "$currentFile"
    exit
fi

# second phase of script
line1=$(grep -nr "pick $commit1" $1 | cut -f1 -d:)
if [ -z $line1 ]; then
    echo "Could not find a match for $commit1"
    exit
fi
line2=$(grep -nr "pick $commit2" $1 | 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 $1
#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" "$1")
    nextLineIndex=$(expr $currentLineIndex - 1)
    nextLine=$(sed -n "${nextLineIndex}p" "$1")
    cat $1 | sed $currentLineIndex"s/.*/$nextLine/" | sed $nextLineIndex"s/.*/$currentLine/" >| $1
done

#change the pick to squash
cat $1 | sed $(expr $oldLine + 1)"s/pick/squash/" >| $1

示例使用:$ GIT_SEQUENCE_EDITOR=$(./rebase.sh d199 a548) git rebase -i 95e2a7c

答案 2 :(得分:0)

一个更简单的替代方案,如果您只想修复暂存区域中的现有提交:(感谢@Andrew C将我指向--fixup

function git_fix {
    git commit --fixup=$1
    GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "$1^" #empty script
}

作为git别名:

fix="!f() {\
    git commit --fixup=$1;\
    GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "$1^";\
}; f"