我有如下情况:
- 我从一个主仓库(X)创建了克隆(Y),因为有很多人在Y上工作,我们没有做任何
rebase
而只做了merge
。当我们想要将Y交付(push
)给X时,我们希望进行一次rebase
,以使事情变得清晰明了。
问题是,当进行rebase
时,我们被要求做之前已经完成的所有merge
步骤。除了重新执行合并操作的解决方案之外,是否有其他解决方案?
我认为这应该很简单,因为我们已经解决了冲突的合并。
我有如下情况:
rebase
而只做了merge
。当我们想要将Y交付(push
)给X时,我们希望进行一次rebase
,以使事情变得清晰明了。问题是,当进行rebase
时,我们被要求做之前已经完成的所有merge
步骤。除了重新执行合并操作的解决方案之外,是否有其他解决方案?
我认为这应该很简单,因为我们已经解决了冲突的合并。
git merge --squash
现在是我在大量工作和多次合并之后首选的变基方式(参见此答案)。如果你正在工作的分支叫做 my-branch
,并且你想要从 main
进行变基,只需按照以下步骤操作:
git checkout my-branch
git branch -m my-branch-old # rename from my-branch to my-brand-old
git checkout main
git checkout -b my-branch # make new my-branch branch
git merge --squash my-branch-old # squash and merge changes from old branch
git commit
git branch --set-upstream-to origin/my-branch
并可选地添加 git push --force
。如果没有这样做,新的 my-branch
将不会与远程分支链接。强制推送允许在远程上重写历史记录,只需在其历史记录中有压缩提交即可。也就是说,我的评论假设除了我自己之外没有其他人跟踪远程分支,以避免破坏历史记录。 - Steve Bgit read-tree -u -m dev
来更新您的工作树以匹配dev
分支。然后您可以将所有内容提交为一个大型提交,并像平常一样将其合并到主分支中。--squash
参数合并时才会相同。如果使用普通合并,如果在分支上有 N 个提交,则将向主分支添加 N 或 N+1 个提交。建议使用上述的 merge --squash
命令,它将始终向主分支添加一个单独的提交。 - peterflynn两点说明:
git rerere
,则可以避免在变基过程中出现合并冲突,这对于这种情况非常有用。
更多信息请参见git rerere
。您可以使用以下方式将分支中的所有更改合并到master
分支的一个新提交中:
git diff master > my_branch.patch
git checkout master
patch -p1 < my_branch.patch
接着对文件进行分阶段操作并提交。
关于合并冲突的重放,您可以使用git rerere维护一个数据库来记录已经解决过的合并冲突,这样进行导入操作时如果出现相同的冲突,繁琐的部分将会自动完成。
https://hackernoon.com/fix-conflicts-only-once-with-git-rerere-7d116b2cec67
git config --global rerere.enabled true
需要注意的一点是,如果您错误地解决了某些问题,下一次也会自动产生问题,而您可能并没有意识到。
更加正式的文档可在此处找到:https://git-scm.com/docs/git-rerere
我发现@sky的回答很有帮助。然后我将其制作成了一个压缩重置函数。
假设您在your-branch
上,这样做就是创建一个名为your-branch-tmp
的分支,该分支是在主分支上执行merge --squash
的结果。它还保留了所有提交消息并允许您进行编辑。重要的是,它也不会影响您当前的分支。
运行压缩重置后,如果您对其满意,则必须对tmp分支进行硬重置。然后实际上您已经完成了一个压缩重置。
function squash-rebase() {
MESSAGES="$(git log $(git merge-base main HEAD)..HEAD --reverse --format=%B)"
SRC_BRANCH="$(git_current_branch)"
TMP_BRANCH="$(git_current_branch)-tmp"
echo "creating temp branch $TMP_BRANCH from $(git_current_branch)"
git checkout -b $TMP_BRANCH main # create tmp branch from main and checkout
git merge $SRC_BRANCH --squash
git commit -m "$MESSAGES" -n
git commit --amend -n # just so you can edit the messages
git checkout $SRC_BRANCH
echo "IMPORTANT: run git reset --hard $TMP_BRANCH to complete squash rebase."
echo "First, though, you may run git diff $TMP_BRANCH to make sure no changes."
echo "Finally, delete the tmp branch with git branch -D $TMP_BRANCH"
}