说我有这个:
I1 -- I2 -- I3
\ \
F1 -- F2 -- ? -- F3 -- F4 -- F5
我创建了一个新的功能分支F,我提交了提交F1和F2,之后我想整合来自集成分支的更改以防止冲突。
所以我这样做:
git fetch origin I
git checkout F
git rebase origin/I
那么它现在看起来应该是这样的:
I1 -- I2 -- I3
\
F1 -- F2 -- F3 -- F4 -- F5
我的问题是 - 现在我想将提交F1-F5压缩成一个提交。我怎样才能安全地压缩提交?
我可以做git reset --soft x
,但什么是x
?如何找到要返回的提交?我不想失去集成分支的任何历史记录。
在英语中,我认为这将是我的分支上最旧的提交,它不在集成分支中,而且还提交的地方比集成分支的任何提交更年轻。 (?)如果我做一个git merge
而不是git rebase
(偶然),可能会发生后一种情况。
试试git fetch && GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick/squash/'" git rebase -i @{u}
(你可以把它压成别名,shell或Git-to-shell)。
请考虑以下事项:当您运行git rebase
时,您告诉git rebase
将副本放在何处。也就是说,你运行:
git checkout $branch
git rebase $onto
其中$branch
是你的分支的名称,$onto
是指定如何进行rebase的事情。由于副本在$onto
指定的提交之后,$onto
自动成为你的git reset --soft
的正确点。
如果你有git pull --rebase
为你运行git rebase
,你就放弃了对$onto
的直接控制。 git pull
命令首先为某些git fetch $remote
运行$remote
,然后使用git fetch
记录的获取信息(在$GIT_DIR/FETCH_HEAD
中)作为$onto
参数。
由于fork-point代码,这里有一些额外的复杂性,但在现代Git中,你有git fetch
将更新$upstream
的优势,其中$upstream
是当前分支的上游,之后git rebase
将使用$upstream
并完成所有自动叉点东西,这样$upstream
仍然是正确的。在这种情况下,使用:
. git-sh-setup
branch=$(git symbolic-ref -q --short HEAD) || die 'not currently on a branch'
remote=$(git config --get branch.$branch.remote) || die 'current branch has no upstream'
git fetch $remote && git rebase || die 'fetch or rebase failed'
git reset --soft $upstream && git commit
作为你的脚本(例如命名为git-rebase-and-squash
中的$PATH
并以git rebase-and-squash
运行)将大部分都可以。
但是,您可能想要读取最后一行,而不是直接使用reset --soft
和git commit
:
GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick/squash/'" git rebase -i $upstream
将你所有的pick
s转换为squash
es,在这种情况下你甚至不需要更早的git rebase
,所以整个脚本崩溃到git fetch
,然后是git rebase -i @{upstream}
。 (您是否仍希望自动执行序列编辑取决于您。)
如果您不介意略有误导性的错误消息,则也不需要检查。默认情况下运行git fetch
将从origin
获取,如果没有当前分支或者当前分支没有上游,@upstream
将失败,因此可以将其缩减为两个命令长的脚本或别名:
git fetch && GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick/squash/'" git rebase -i @{u}
如果你想通过软复位挤压,那么:
git reset --soft HEAD~5
这会将HEAD指针从F5
的当前位置移回I3
提交。但是,软复位不会触及工作目录和阶段。所以净效应将是你的舞台将反映5个F
提交。然后,当你提交时,你将有效地将这5个提交压缩为一个:
git commit -m 'squashed 5 F commits'
这让你:
I1 -- I2 -- I3 -- C
作为替代方案,您还可以执行交互式rebase:
git rebase -i HEAD~5
您将更改每个要从pick
压缩到squash
的提交,然后完成rebase。