在本章中我们将介绍常见的git rebase
用法。
一、合并commit
假设我们现在有如下的log
:
commit 72ff789d5a79cb0e79728bc86355c067b24a5b34 (HEAD -> master)
Author: SwordofMorning <969211735@qq.com>
Date: Thu Jul 25 14:53:56 2024 +0800
rebase_02
commit 0cd3a6179b7446de5e9f12e4a6cbd85c2553e959
Author: SwordofMorning <969211735@qq.com>
Date: Thu Jul 25 14:53:33 2024 +0800
rebase_01
commit 3bbb67450967dd8de8f6271f8f8e60119b77c3f4 (origin/master, origin/HEAD)
Author: SwordofMorning <969211735@qq.com>
Date: Thu Jul 25 11:04:09 2024 +0800
RV1126 05, Trick 02
commit 261762b3aeae2e52de8484424079bc3989c8ac44
Author: SwordofMorning <969211735@qq.com>
我们希望合并两个最新的、未提交的commit,我们可以使用:
git rebase -i HEAD~2
这里的编辑器使用vim,如果使用vscode则会遇到神秘力量,gitlens插件似乎也不支持合并commit这种rebase操作。编辑器中会出现:
pick 0cd3a61 rebase_01
pick 72ff789 rebase_02
# Rebase 3bbb674..72ff789 onto 3bbb674 (2 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
我们将其中修改为:
pick 0cd3a61 rebase_01
squash 72ff789 rebase_02
pick
表示保留当前commit,squash
表示将当前commit与上一个commit合并。保存之后则是合并后的commit信息:
# This is a combination of 2 commits.
# This is the 1st commit message:
rebase_01
# This is the commit message #2:
rebase_02
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Thu Jul 25 14:53:33 2024 +0800
#
# interactive rebase in progress; onto 3bbb674
# Last commands done (2 commands done):
# pick 0cd3a61 rebase_01
# squash 72ff789 rebase_02
# No commands remaining.
# You are currently rebasing branch 'master' on '3bbb674'.
#
# Changes to be committed:
# new file: rebase_01.txt
# new file: rebase_02.txt
#
保存之后我们可以发现最新的两个commit已经被合并了。
二、合并分支
假设我们现在有如下的工作树:
(master)B -> A
(dev)D -> C -> B -> A
↓
(master)E -> B -> A
(dev)D -> C -> E -> B -> A
我们在(dev)B -> A
上提交了D -> C -> B
;另一个人在(master)B -> A
上提交了E -> B
。这里我们使用rebase
来合并的话,将会产生D -> C -> E -> B
的线性提交记录,而不会有merge一样的交叉。下面通过具体的例子来看一下。
下面我们在master
上有一条新的commit,在dev上有两条commit,我们希望将其合并。
此时我们切换到dev
分支,使用:
# 切换分支
git checkout dev
# 开始合并
git rebase master
此时我们需要处理冲突,在处理完成之后使用git status
来确认是否已经没有需要继续的事项:
git status
interactive rebase in progress; onto 3369821
Last commands done (2 commands done):
pick 6bf296f dev
pick 68ec855 dev 02
No commands remaining.
You are currently rebasing branch 'dev' on '3369821'.
(all conflicts fixed: run "git rebase --continue")
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: Computer Science/Academic/Git/03.md
modified: Computer Science/Academic/Git/03.md
此时我们还需要继续:git rebase --continue
,直到git status
提示我们:
nothing to commit, working tree clean
我们可以发现,此时的工作树如下所示:
我们切换到master
上,在git merge dev
之后删除dev
分支,得到: