git-rebase

发布时间 2023-07-13 15:24:21作者: lxd670

1.合并commit

1-1.说明

一般使用git rebase -i <start_commit><end_commit>默认是当前最新HEAD

范围: (start_commit, end_commit]

rebase合并一般会进入commit挑选commit信息编辑的vim界面

git rebase -i <start_commit> <end_commit>

1-2.合并参数

命令 缩写 含义
pick p 保留该 commit
reword r 保留该 commit,但需要修改该 commit 的注释
edit e 保留该 commit, 但我要停下来修改该提交(不仅仅修改注释)
squash s 将该 commit 合并到前一个 commit
fixup f 将该 commit 合并到前一个 commit,但不要保留该提交的注释信息
exec x 执行 Shell 命令
drop d 丢弃该 commit

1-3.生成测试

git init
echo "a" > a.txt && git add . && git commit -m "add a.txt"
echo "b" > b.txt && git add . && git commit -m "add b.txt"
echo "c" > c.txt && git add . && git commit -m "add c.txt"
echo "d" > d.txt && git add . && git commit -m "add d.txt"
echo "e" > e.txt && git add . && git commit -m "add e.txt"
echo "f" > f.txt && git add . && git commit -m "add f.txt"
echo "g" > g.txt && git add . && git commit -m "add g.txt"
git log --oneline --graph
* 12fd5e8 (HEAD -> master) add g.txt
* 3ce2c47 add f.txt
* 00bfccd add e.txt
* 66f3e76 add d.txt
* f73f8c0 add c.txt
* 7fac03e add b.txt
* b129743 add a.txt

1-4.使用squash合并

注意: 不包含f73f8c0,合并的是66f3e76-12fd5e8

1-4-1.执行合并

git rebase -i f73f8c0

1-4-2.挑选commit

1-4-3.编辑合并信息

[detached HEAD 902fd29] add d e f g
 Date: Wed Jul 5 14:01:35 2023 +0800
 4 files changed, 4 insertions(+)
 create mode 100644 d.txt
 create mode 100644 e.txt
 create mode 100644 f.txt
 create mode 100644 g.txt
Successfully rebased and updated refs/heads/master.

1-4-3.查看日志

git log --oneline --graph
* 902fd29 (HEAD -> master) add d e f g
* f73f8c0 add c.txt
* 7fac03e add b.txt
* b129743 add a.txt

1-5.使用fixup合并

fixup不会进入msg编辑页面

1-5-1.执行合并

git rebase -i f73f8c0

1-5-2.挑选commit

把原有的add d.txt改为add d,e,f,g不会生效

Successfully rebased and updated refs/heads/master.

1-5-3.查看日志

git log --oneline --graph 
* 82b270e (HEAD -> master) add d.txt
* f73f8c0 add c.txt
* 7fac03e add b.txt
* b129743 add a.txt

1-6.区间合并

注意: 区间合并时,合并完会变为游离分支

1-6-1.执行合并

git rebase -i 7fac03e 00bfccd

1-6-2.挑选commit

# 改之前
pick f73f8c0 add c.txt
pick 66f3e76 add d.txt
pick 00bfccd add e.txt
# 改完后
pick f73f8c0 add c.txt
s 66f3e76 add d.txt
s 00bfccd add e.txt

1-6-3.编辑合并信息

# 改之前
# This is a combination of 3 commits.
# This is the 1st commit message:
add c.txt
# This is the commit message #2:
add d.txt
# This is the commit message #3:
add e.txt
# 改完后
# This is a combination of 3 commits.
# This is the 1st commit message:

add c,d,e
[detached HEAD 9770b06] add c,d,e
 Date: Wed Jul 5 14:01:23 2023 +0800
 3 files changed, 3 insertions(+)
 create mode 100644 c.txt
 create mode 100644 d.txt
 create mode 100644 e.txt
Successfully rebased and updated detached HEAD.

1-6-4.查看分支

git branch
* (HEAD detached from refs/heads/master)
  master

1-6-5.创建新分支

git switch -c dev
Switched to a new branch 'dev'

1-6-6.查看日志

git log --oneline --graph --all
* 9770b06 (HEAD -> dev) add c,d,e
| * 12fd5e8 (master) add g.txt
| * 3ce2c47 add f.txt
| * 00bfccd add e.txt
| * 66f3e76 add d.txt
| * f73f8c0 add c.txt
|/  
* 7fac03e add b.txt
* b129743 add a.txt

2.变基

2-1.变基说明

在合并分支时,如果dev分支没有指向master分支最新的HEAD,合并两个会生成一个提交(no-fast-forward)

如果使用变基,把dev分支指向master分支最新的HEAD,那么会变为快进合并(fast-forward)

2-2.无冲突变基

2-2-1.查看分支情况

git log --oneline --graph --all
* fbba993 (HEAD -> master) add b.txt
| * 80923fc (dev) add dev_2.txt
| * b9ccd97 add dev_1.txt
|/  
* a612327 add a.txt

2-2-2.切换到dev分之

git switch dev

2-2-3.变基

git rebase master 
Successfully rebased and updated refs/heads/dev.

2-2-4.查看日志

git log --oneline --graph --all
* 15d529e (HEAD -> dev) add dev_2.txt
* 5306bba add dev_1.txt
* fbba993 (master) add b.txt
* a612327 add a.txt

2-3.有冲突变基

2-3-1.查看分支情况

git log --oneline --graph --all
* 9b305d9 (HEAD -> master) master update a.txt
* fbba993 add b.txt
| * 9357d18 (dev) dev update a.txt
| * 80923fc add dev_2.txt
| * b9ccd97 add dev_1.txt
|/  
* a612327 add a.txt

2-3-2.切换到dev分之

git switch dev

2-3-3.变基出错

git rebase --abort:取消变基

git rebase --skip:跳过变基冲突,冲突文件按master分支为标准

git rebase master 
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
error: could not apply 9357d18... dev update a.txt
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 9357d18... dev update a.txt
git status
interactive rebase in progress; onto 9b305d9
Last commands done (3 commands done):
   pick 80923fc add dev_2.txt
   pick 9357d18 dev update a.txt
  (see more in file .git/rebase-merge/done)
No commands remaining.
You are currently rebasing branch 'dev' on '9b305d9'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
        both modified:   a.txt

no changes added to commit (use "git add" and/or "git commit -a")

2-3-4.修改冲突文件

a
<<<<<<< HEAD
master
=======
m dev
>>>>>>> 9357d18 (dev update a.txt)
a
master
m dev

2-3-5.继续变基

git add a.txt
git rebase --continue

[detached HEAD 891900b] dev update a.txt New
 1 file changed, 4 insertions(+)
Successfully rebased and updated refs/heads/dev.

2-3-5.查看日志

git log --oneline --graph --all
* 891900b (HEAD -> dev) dev update a.txt New
* c276738 add dev_2.txt
* f1256d0 add dev_1.txt
* 9b305d9 (master) master update a.txt
* fbba993 add b.txt
* a612327 add a.txt

2-4.跳过冲突的编辑

注意:如果跳过冲突文件,会丢弃当前分支对冲突文件的修改。

2-4-1.查看分支情况

git log --oneline --graph --all
* b13e82f (HEAD -> dev) add dev_3.txt
* 9357d18 dev update a.txt
* 80923fc add dev_2.txt
* b9ccd97 add dev_1.txt
| * 9b305d9 (master) master update a.txt
| * fbba993 add b.txt
|/  
* a612327 add a.txt

2-4-2.变基出错

git rebase master
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
error: could not apply 9357d18... dev update a.txt
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 9357d18... dev update a.txt
cat a.txt
a
<<<<<<< HEAD
master
=======
m dev
>>>>>>> 9357d18 (dev update a.txt)

2-4-3.跳过冲突

git rebase --skip
Successfully rebased and updated refs/heads/dev.

2-4-5.查看文件

cat a.txt
a
master

2-4-5.查看日志

git log --oneline --graph --all
* c1eea46 (HEAD -> dev) add dev_3.txt
* d5d85bf add dev_2.txt
* 5b70ae5 add dev_1.txt
* 9b305d9 (master) master update a.txt
* fbba993 add b.txt
* a612327 add a.txt

2-5.撤销编辑

2-5-1.查看reflog

git reflog
891900b (HEAD -> dev) HEAD@{0}: rebase (continue) (finish): returning to refs/heads/dev
891900b (HEAD -> dev) HEAD@{1}: rebase (continue): dev update a.txt New
c276738 HEAD@{2}: rebase (pick): add dev_2.txt
f1256d0 HEAD@{3}: rebase (pick): add dev_1.txt
9b305d9 (master) HEAD@{4}: rebase (start): checkout master
9357d18 HEAD@{5}: checkout: moving from master to dev
9b305d9 (master) HEAD@{6}: commit: master update a.txt
fbba993 HEAD@{7}: checkout: moving from dev to master
9357d18 HEAD@{8}: commit: dev update a.txt
80923fc HEAD@{9}: checkout: moving from master to dev
fbba993 HEAD@{10}: commit: add b.txt
a612327 HEAD@{11}: checkout: moving from dev to master
80923fc HEAD@{12}: commit: add dev_2.txt
b9ccd97 HEAD@{13}: commit: add dev_1.txt
a612327 HEAD@{14}: checkout: moving from master to dev
a612327 HEAD@{15}: commit (initial): add a.txt

2-5-2.撤销

reset到rebase (start)之前的commit

git reset --hard 9357d18
HEAD is now at 9357d18 dev update a.txt

2-5-3.查看日志

git log --oneline --graph --all
* 9b305d9 (master) master update a.txt
* fbba993 add b.txt
| * 9357d18 (HEAD -> dev) dev update a.txt
| * 80923fc add dev_2.txt
| * b9ccd97 add dev_1.txt
|/  
* a612327 add a.txt