git-rebase進階使用
git rebase
進階使用
推薦書籍: 《git pro》
推薦教程: atlassian
本地獲取幫助:
git help <command>
-
rebase
最強大的地方在於可以按需移動提交併對其進行編輯更改,當然前提是在個人分支上 -
最好對git中的一些概念預先有一定的瞭解
-
再次強調:
git rebase
相關命令只允許在個人分支上使用
目錄:
- 本文alias說明
- 用法一:將當前分支的提交變基到目標分支
- 用法二:將當前分支變基到之前的提交, 重寫其後的提交
- 用法三:將當前分支某一段提交變基到目標分支
- 用法四:變基時保留合併提交
- 衝突
alias
說明
git ll
=git log --oneline
git br
=git branch
git st
=git status
git ci
=git commit
git lh
=log --pretty=format:'%Cred%h %C(yellow)%ad%Creset %Cred%s%Creset %Cblue[%an] %C(yellow)%d' --graph --date=short --topo-order
用法一
將當前分支的提交變基到目標分支: git rebase <upstream> [<branch>]
-
<upstream>
:目標分支或新基點 -
如果提供
<branch>
,則會執行git checkout <branch>
,預設為HEAD
>git br
* master
test
>git ll master
1a17ba1 (HEAD -> master) add c
4428c06 add a
>git ll test
d691c94 (test) add b
4428c06 (HEAD -> master) add a
>git co test
>git rebase master (或 git rebase master test)
First, rewinding head to replay your work on top of it...
Applying: add b
>git br
master
* test
>git ll test
30cec3f (HEAD -> test) add b
1a17ba1 (master) add c
4428c06 add a
>git ll master
1a17ba1 (master) add c
4428c06 add a
可能的場景:
- 在將當前分支合併到主分支前執行變基操作,然後再合併到主分支,可以實現
fast-forward
用法二
將當前分支變基到之前的某一提交, 重寫其後的提交:git rebase -i <upstream> [<branch>]
>git ll test
4a4633c (HEAD -> test) change d
f3ff56f add d
30cec3f add b
1a17ba1 (master) add c
4428c06 add a
> git rebase -i HEAD~2
>>pick f3ff56f add d
>>pick 4a4633c change d
//改為並儲存:
>>pick f3ff56f add d
>>suqash 4a4633c change d
//輸入提交資訊並儲存:
>>add and change d
[detached HEAD fb38e3f] add and change d
Date: Mon Jul 22 19:46:25 2019 +0800
1 file changed, 2 insertions(+)
create mode 100644 d
Successfully rebased and updated refs/heads/test.
>git ll test
fb38e3f (HEAD -> test) add and change d
30cec3f add b
1a17ba1 (master) add c
4428c06 add a
互動式rebase
的選項說明:
pick f3ff56f add d
pick 4a4633c change d
# Rebase 30cec3f..4a4633c onto 30cec3f (2 commands) //表示將30cec3f..4a4633c(左開右閉)變基到30cec3f,包含2條命令,即有兩個提交需要處理
#
# Commands:
# p, pick = use commit //表示正常使用該提交
# r, reword = use commit, but edit the commit message //正常使用該提交,但會提示修改提交資訊
# e, edit = use commit, but stop for amending //正常使用該提交內容,但提交後會停下,此時可以執行git commit --amend或者其他命令,最後git rebase --continue
# s, squash = use commit, but meld into previous commit //與前一提交合並,會提示輸入提交資訊
# f, fixup = like "squash", but discard this commit's log message //與上一提交合並,但不會使用該提交資訊 類似於git commit --amend --no-edit
# x, exec = run command (the rest of the line) using shell //執行給定命令
# d, drop = remove commit //移除該提交
#
# 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.
#
# Note that empty commits are commented out //會忽略由merge生成的提交
可能的場景:
- 可以在自己本地分支上將多個commit合併為一個:
squash
- 可以在自己本地分支上重新規劃提交順序
- 可以在自己本地分支上重寫某提交註釋資訊:
reword
,類似git commit --amend
的功能 - 可以在自己本地分支上移除某提交:
drop
或直接刪除該行 - 可以在自己本地分支上移除空
merge commit
:
D:\tmp\gittest\git1>git lh
* 44dd22a 2019-07-24 add f [userName] (HEAD -> master)
* 0141788 2019-07-24 Merge branch 'test' [userName] //空提交
|\
| * e52ab99 2019-07-24 add e [userName] (test)
* | ea9bded 2019-07-24 change d [userName]
* | 7656327 2019-07-24 add d [userName]
* | 4940b1f 2019-07-24 add c [userName]
|/
* f41fe7f 2019-07-24 add b [userName]
* 1a32cb0 2019-07-23 change a [userName]
* 1fc8279 2019-07-23 add a [userName]
D:\tmp\gittest\git1>git rebase -i 4940b1f
Successfully rebased and updated refs/heads/master.
D:\tmp\gittest\git1>git lh
* 02e856a 2019-07-24 add f [userName] (HEAD -> master)
* a94b7a5 2019-07-24 add e [userName]
* ea9bded 2019-07-24 change d [userName]
* 7656327 2019-07-24 add d [userName]
* 4940b1f 2019-07-24 add c [userName]
* f41fe7f 2019-07-24 add b [userName]
* 1a32cb0 2019-07-23 change a [userName]
* 1fc8279 2019-07-23 add a [userName]
如果merge commit
不是空提交,則要手動解決衝突:
D:\tmp\gittest\git1>git lh
* 8a5ce3e 2019-07-24 add e [userName] (HEAD -> master)
* f037d3b 2019-07-24 Merge branch 'fix' Conflicts:f [userName] //合併時解決衝突
|\
| * ec2312c 2019-07-24 change f fix [userName] (fix)
* | e3a88f2 2019-07-24 change f master [userName]
|/
* 02e856a 2019-07-24 add f [userName]
* a94b7a5 2019-07-24 add e [userName]
* ea9bded 2019-07-24 change d [userName]
* 7656327 2019-07-24 add d [userName]
* 4940b1f 2019-07-24 add c [userName]
* f41fe7f 2019-07-24 add b [userName]
* 1a32cb0 2019-07-23 change a [userName]
* 1fc8279 2019-07-23 add a [userName]
D:\tmp\gittest\git1>git rebase -i e3a88f2
error: could not apply ec2312c... change f fix
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Could not apply ec2312c... change f fix
Auto-merging f
CONFLICT (content): Merge conflict in f
D:\tmp\gittest\git1>git st
interactive rebase in progress; onto e3a88f2
Last command done (1 command done):
pick ec2312c change f fix
Next command to do (1 remaining command):
pick 8a5ce3e add e
(use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'master' on 'e3a88f2'.
(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 reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: f
no changes added to commit (use "git add" and/or "git commit -a")
D:\tmp\gittest\git1>gvim f
D:\tmp\gittest\git1>git add f
D:\tmp\gittest\git1>git ci
[detached HEAD e531346] change f fix Conflicts:f2
1 file changed, 1 insertion(+)
D:\tmp\gittest\git1>git st
interactive rebase in progress; onto e3a88f2
Last command done (1 command done):
pick ec2312c change f fix
Next command to do (1 remaining command):
pick 8a5ce3e add e
(use "git rebase --edit-todo" to view and edit)
You are currently editing a commit while rebasing branch 'master' on 'e3a88f2'.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
nothing to commit, working tree clean
D:\tmp\gittest\git1>git rebase --continue
Successfully rebased and updated refs/heads/master.
D:\tmp\gittest\git1>git lh
* c5516c4 2019-07-24 add e [userName] (HEAD -> master)
* e531346 2019-07-24 change f fix Conflicts:f2 [userName]
* e3a88f2 2019-07-24 change f master [userName]
* 02e856a 2019-07-24 add f [userName]
* a94b7a5 2019-07-24 add e [userName]
* ea9bded 2019-07-24 change d [userName]
* 7656327 2019-07-24 add d [userName]
* 4940b1f 2019-07-24 add c [userName]
* f41fe7f 2019-07-24 add b [userName]
* 1a32cb0 2019-07-23 change a [userName]
* 1fc8279 2019-07-23 add a [userName]
- 可以在自己本地分支上拆分commit:互動式
rebase
時選擇edit
,之後可以對該commit進行操作
D:\tmp\gittest\git1>git br
* master
D:\tmp\gittest\git1>git lh
* 645a536 2019-07-24 add d [userName] (HEAD -> master)
* 94f1b39 2019-07-24 add b c [userName] //準備拆分該提交
* 1a32cb0 2019-07-23 change a [userName]
* 1fc8279 2019-07-23 add a [userName]
D:\tmp\gittest\git1>git rebase -i HEAD~2
pick 94f1b39 add b c
pick 645a536 add d
改為
edit 94f1b39 add b c
pick 645a536 add d
Stopped at 94f1b39... add b c
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
D:\tmp\gittest\git1>git reset HEAD~1 //撤銷提交
D:\tmp\gittest\git1>ls
a b c
D:\tmp\gittest\git1>git st
interactive rebase in progress; onto 1a32cb0
Last command done (1 command done):
edit 94f1b39 add b c
Next command to do (1 remaining command):
pick 645a536 add d
(use "git rebase --edit-todo" to view and edit)
You are currently editing a commit while rebasing branch 'master' on '1a32cb0'.
(use "git commit --amend" to amend the current commit)
(use "git rebase --continue" once you are satisfied with your changes)
Untracked files:
(use "git add <file>..." to include in what will be committed)
b
c
nothing added to commit but untracked files present (use "git add" to track)
D:\tmp\gittest\git1>git add b //拆解提交1
D:\tmp\gittest\git1>git ci -m "add b"
[detached HEAD f41fe7f] add b
1 file changed, 2 insertions(+)
create mode 100644 b
D:\tmp\gittest\git1>git add c //拆解提交2
D:\tmp\gittest\git1>git ci -m "add c"
[detached HEAD 4940b1f] add c
1 file changed, 2 insertions(+)
create mode 100644 c
D:\tmp\gittest\git1>git rebase --continue
Successfully rebased and updated refs/heads/master.
D:\tmp\gittest\git1>git lh
* 7656327 2019-07-24 add d [userName] (HEAD -> master)
* 4940b1f 2019-07-24 add c [userName]
* f41fe7f 2019-07-24 add b [userName]
* 1a32cb0 2019-07-23 change a [userName]
* 1fc8279 2019-07-23 add a [userName]
- 可以在自己本地分支上同時完成以上調整
用法三
將當前分支某一段提交變基到目標分支:git rebase --onto <newBase> <ref-start> <ref-end>
- 因為提供了
<ref-end>
這個引數,預設會在後臺執行git checkout <branch>
命令,如果沒有分支指向它,則會處於detached
狀態。 --onto
選項相當於執行了git reset --hard <newBase>
D:\tmp\gittest\master>git ll test
fb38e3f (HEAD -> test) add and change d
30cec3f add b
1a17ba1 (master) add c
4428c06 add a
D:\tmp\gittest\master>git ll master
1a17ba1 (master) add c
4428c06 add a
D:\tmp\gittest\master>git co master
Switched to branch 'master'
D:\tmp\gittest\master>git merge test
Updating 1a17ba1..fb38e3f
Fast-forward
b | 1 +
d | 2 ++
2 files changed, 3 insertions(+)
create mode 100644 b
create mode 100644 d
D:\tmp\gittest\master>git ll master
fb38e3f (HEAD -> master, test) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
D:\tmp\gittest\master>git ll test
40dcfec (HEAD -> test) change g
dc0ddd2 add g
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
D:\tmp\gittest\master>git ll dev
87c6bae (dev) change e
8d7cfc9 add e
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
D:\tmp\gittest\master>git ll fix
a355be9 (fix) change f
0e24647 add f
87c6bae (dev) change e
8d7cfc9 add e
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
D:\tmp\gittest\master>git rebase --onto test dev fix
First, rewinding head to replay your work on top of it...
Applying: add f
Applying: change f
D:\tmp\gittest\master>git ll fix
974accb (HEAD -> fix) change f
51f8e08 add f
40dcfec (test) change g
dc0ddd2 add g
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
如果沒有分支指向<ref-end>
,比如執行git rebase --onto fix master dev~1
後,HEAD
處於遊離狀態,沒有指向任何分支,還需要以下操作:
D:\tmp\gittest\master>git ll dev
87c6bae (dev) change e
8d7cfc9 add e
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
D:\tmp\gittest\master>git rebase --onto fix master dev~1
First, rewinding head to replay your work on top of it...
Applying: add e
D:\tmp\gittest\master>git st
HEAD detached from a355be9
nothing to commit, working tree clean
D:\tmp\gittest\master>git br
* (HEAD detached from a355be9)
dev
fix
master
test
D:\tmp\gittest\master>git co dev
Warning: you are leaving 1 commit behind, not connected to
any of your branches:
13ea505 add e
If you want to keep it by creating a new branch, this may be a good time
to do so with:
git branch <new-branch-name> 13ea505
Switched to branch 'dev'
D:\tmp\gittest\master>git reset --hard 13ea505
HEAD is now at 13ea505 add e
D:\tmp\gittest\master>git br
* dev
fix
master
test
D:\tmp\gittest\master>git ll dev
13ea505 (HEAD -> dev) add e
974accb (fix) change f
51f8e08 add f
40dcfec (test) change g
dc0ddd2 add g
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
可能的使用場景:
- 將某一臨時分支的一段提交變基到目標分支
- 提交較少情況下,可使用
git cherry-pick
代替 - 可以移除部分不需要的
commit
: 執行git rebase --onto dev~3 dev~1 dev
,將移除dev~2,dev~1
用法四
變基時保留合併提交:git rebase -i -p --onto <newBase> <upstream> [<branch>]
- 如果要保留原
merge commit
,即保留原結構,如圖示Q
,需加選項--preserve-merges
,簡寫-p
D:\tmp\gittest\master>git ll
f254843 (HEAD -> dev) Merge branch 'fix' into dev
0f22361 (fix) add k
3fb9d97 add i
1e45291 change h
f847d82 add h
13ea505 add e
974accb change f
51f8e08 add f
40dcfec change g
dc0ddd2 add g
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
D:\tmp\gittest\master>git lh
* f254843 2019-07-23 Merge branch 'fix' into dev [userName] (HEAD -> dev)
|\
| * 0f22361 2019-07-23 add k [userName] (fix)
* | 3fb9d97 2019-07-23 add i [userName]
|/
* 1e45291 2019-07-23 change h [userName]
* f847d82 2019-07-23 add h [userName]
* 13ea505 2019-07-23 add e [userName]
* 974accb 2019-07-23 change f [userName]
* 51f8e08 2019-07-23 add f [userName]
* 40dcfec 2019-07-23 change g [userName]
* dc0ddd2 2019-07-23 add g [userName]
* fb38e3f 2019-07-22 add and change d [userName] (master)
* 30cec3f 2019-07-17 add b [userName]
* 1a17ba1 2019-07-22 add c [userName]
* 4428c06 2019-07-17 add a [userName]
D:\tmp\gittest\master>git rebase -p --onto test 13ea505
Successfully rebased and updated refs/heads/dev.
D:\tmp\gittest\master>git lh
* f6c89b0 2019-07-23 Merge branch 'fix' into dev [userName] (HEAD -> dev)
|\
| * 68ad94d 2019-07-23 add k [userName]
* | 3c5453a 2019-07-23 add i [userName]
|/
* f2db9e5 2019-07-23 change h [userName]
* d468e47 2019-07-23 add h [userName]
* bb3eca7 2019-07-23 add j [userName] (test)
* 13ea505 2019-07-23 add e [userName]
* 974accb 2019-07-23 change f [userName]
* 51f8e08 2019-07-23 add f [userName]
* 40dcfec 2019-07-23 change g [userName]
* dc0ddd2 2019-07-23 add g [userName]
* fb38e3f 2019-07-22 add and change d [userName] (master)
* 30cec3f 2019-07-17 add b [userName]
* 1a17ba1 2019-07-22 add c [userName]
* 4428c06 2019-07-17 add a [userName]
D:\tmp\gittest\master>git co fix
Switched to branch 'fix'
D:\tmp\gittest\master>git reset --hard 68ad94d
HEAD is now at 68ad94d add k
D:\tmp\gittest\master>git lh dev
* f6c89b0 2019-07-23 Merge branch 'fix' into dev [userName] (dev)
|\
| * 68ad94d 2019-07-23 add k [userName] (HEAD -> fix)
* | 3c5453a 2019-07-23 add i [userName]
|/
* f2db9e5 2019-07-23 change h [userName]
* d468e47 2019-07-23 add h [userName]
* bb3eca7 2019-07-23 add j [userName] (test)
* 13ea505 2019-07-23 add e [userName]
* 974accb 2019-07-23 change f [userName]
* 51f8e08 2019-07-23 add f [userName]
* 40dcfec 2019-07-23 change g [userName]
* dc0ddd2 2019-07-23 add g [userName]
* fb38e3f 2019-07-22 add and change d [userName] (master)
* 30cec3f 2019-07-17 add b [userName]
* 1a17ba1 2019-07-22 add c [userName]
* 4428c06 2019-07-17 add a [userName]
如果不加-p
選項:
D:\tmp\gittest\master>git co dev
Switched to branch 'dev'
D:\tmp\gittest\master>git rebase --onto test 13ea505
First, rewinding head to replay your work on top of it...
Applying: add h
Applying: change h
Applying: add i
Applying: add k
D:\tmp\gittest\master>git ll
396ffbd (HEAD -> dev) add k
26f83cf add i
303cc06 change h
9e3c0be add h
bb3eca7 (test) add j
13ea505 add e
974accb change f
51f8e08 add f
40dcfec change g
dc0ddd2 add g
fb38e3f (master) add and change d
30cec3f add b
1a17ba1 add c
4428c06 add a
D:\tmp\gittest\master>git lh
* 396ffbd 2019-07-23 add k [userName] (HEAD -> dev)
* 26f83cf 2019-07-23 add i [userName]
* 303cc06 2019-07-23 change h [userName]
* 9e3c0be 2019-07-23 add h [userName]
* bb3eca7 2019-07-23 add j [userName] (test)
* 13ea505 2019-07-23 add e [userName]
* 974accb 2019-07-23 change f [userName]
* 51f8e08 2019-07-23 add f [userName]
* 40dcfec 2019-07-23 change g [userName]
* dc0ddd2 2019-07-23 add g [userName]
* fb38e3f 2019-07-22 add and change d [userName] (master)
* 30cec3f 2019-07-17 add b [userName]
* 1a17ba1 2019-07-22 add c [userName]
* 4428c06 2019-07-17 add a [userName]
衝突
- 當遇到衝突時,
git rebase
會停在第一個有問題的提交,並標記出衝突位置 - 你可以使用
git diff
檢視衝突,當解決每個檔案的衝突後,需要執行git add <filename>
標記衝突已解決 - 解決所有衝突後執行
git rebase --continue
,或者撤銷該命令:git rebase --abort
相關文章
- 學會使用 git-rebaseGit
- SQLMAP進階使用SQL
- Celery 進階使用
- 徹底搞懂 Git-RebaseGit
- Exceptionless(二) - 使用進階Exception
- chrome devtools使用進階——SourcesChromedev
- css進階less的使用CSS
- Zabbix監控使用進階
- 辦公進階:HoudahSpot使用教程
- Hadoop進階命令使用介紹Hadoop
- tar命令基本、進階使用指北
- CSS使用的一些小技巧/高階進階CSS
- 聊聊wireshark的進階使用功能
- HTML5進階FileReader的使用HTML
- 【C進階】#error和#line使用分析Error
- python-進階教程-使用物件屬性進行排序Python物件排序
- Python3進階——使用PyMySQL操作MySQLPythonMySql
- Scanner的進階使用——基礎計算
- flask 專案中使用 bootstrapFileInput(進階篇)Flaskboot
- 【Linux進階】使用grep、find、sed以及awk進行文字操作Linux
- SpreadJS使用進階指南 - 使用 NPM 管理你的專案JSNPM
- NSOperation的進階使用和簡單探討
- NSThead的進階使用和簡單探討
- Redux 進階 -- 編寫和使用中介軟體Redux
- stable diffusion ControlNet使用介紹與進階技巧
- 【C進階】21、巨集定義與使用分析
- 二、RabbitMQ 進階特性及使用場景 [.NET]MQ
- Pandas使用DataFrame進行資料分析比賽進階之路(一)
- 高階前端進階(三)前端
- 高階前端進階(七)前端
- 高階前端進階(五)前端
- vue進階Vue
- SQL進階SQL
- protobuf進階
- gRPC進階RPC
- HBase進階
- 06進階
- Redux 進階Redux