Git Rebase操作


概括

rebase翻譯過來為“變基”,可以理解為改變基礎,它可以用於分支合並和修改提交記錄。

合並分支的區別

我們知道merge操作也可以用於分支合並,但是其和rebase操作有着明顯的不同。假定有一個分支foo在B提交處檢出了分支bar,接着兩個分支各自前進出現了分叉,現在要將bar分支合並回foo分支。

A--B--C----E  foo
    \
     ----D  bar

首先使用merge操作,在foo分支下執行git merge bar命令,git就會在當前分支(即foo分支)下生成一個新的commit節點,從而實現分支的合並。

A--B--C----E---F foo
    \         /
     ----D----
        bar

而reabse操作合並分支的過程與之明顯不同,我們在foo分支下執行git rebase bar命令。

現在來看看rebase操作的合並過程,它先是會暫存當前分支上從分叉開始之后commit節點,然后回退到分叉開始的節點。

stage: C, E

A--B  foo
    \
     ----D  bar

接着bar分支上的所有commit被移動到foo分支上,最后再合並之前暫存的節點。

A--B--D--C'--E' foo
    \
     ----D  bar

可以看到rebase操作合並之后的提交記錄是一條線,而不像merge操作一樣變成棱形,因此rebase操作合並分支會讓提交記錄看起來更加簡潔。

工作流程

接下來基於rebase操作設計一個簡單的分支協同開發流程,流程分為檢出分支前和分支上提交后兩個部分。

檢出之前先在dev分支上pull以獲取分支上最新提交,這樣可以減少后續提交時的沖突,當然該步驟不是必須的。

接着便可以檢出分支來進行開發,下面是該流程的命令示例。

[origin/dev => dev => ${new_branch}]

(dev)$ git pull
(dev)$ git checkout -b ${new_branch}

開發完成並在本地分支上提交后,就可以進行分支的合並了,首先還是先pull拉取dev分支上的最新提交。

接着分為兩種情況,一種是沒有其他人提交顯示“Already up to date.”,這時候就直接切換到dev分支,然后執行rebase操作合並分支,最后提交到遠程。

還有一種當然是有人提交過了,這時候就要先執行rebase操作將dev分支合並到當前開發的分支,接着可能就會出現沖突,需要手動修改沖突后執行git add ${conflict_file}git rebase --continue完成沖突修改。

沖突修改之后的操作和前面是一樣的這里不再敘述,詳細請參考下面的命令示例。

[${new_branch} => dev => origin/dev]

(${new_branch})$ git pull origin dev:dev
=========IF NOT UP TO DATE=========
(${new_branch})$ git rebase dev
(${new_branch})$ <fix the conflict>
===================================
($(new_branch))$ git checkout dev
(dev)$ git rebase ${new_branch}
(dev)$ git push

修改提交記錄

rebase操作除了合並分支,還可以用於提交記錄的修改。

當然一般不推薦在多人協同開發的分支上修改提交記錄,一來是修改記錄時的誤操作可能會導致提交數據丟失。

二來是使用rebase修改提交記錄后,需要使用--force選項強制推送到遠程,假設剛好有其他人提交了代碼而你沒有及時更新,就會導致其他人的代碼被你覆蓋掉。

rebase操作修改提交記錄其實也很簡單,先是執行命令git rebase -i <START> [END],選項-i指的是使用交互式操作方式,后面兩個參數是操作的范圍。

這里<START>指的是開始的提交記錄,而[END]則是結束的提交記錄,如果結束的提交記錄省略則默認為HEAD。注意這里范圍是前面為開區間后面為閉區間,用區間表示為(START, END]。提交記錄既可以用哈希值表示,也可以用頭指針的偏移值表示,例如HEAD~1表示頭指針指向的上一個提交。

上面命令執行完之后,就會出現如下格式的文本,同commit一樣都是使用編輯器打開,修改完成后保存即可。

pick acaa54 Add `demo.md`
pick baed03 Add one line

每一行代表一個提交記錄,第一個字段是對提交記錄的操作命令,第二個字段是提交記錄的哈希值,最后則是提交記錄的注釋。

下面是完整的操作命令和其作用,默認為pick命令即表示使用該提交記錄且不做更改。

# 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.

總結

雖然rebase操作功能強大,但掌握其正確使用才是重中之重。還有使用rebase還是merge合並分支仍有爭議,兩種方式各有利弊,這需要團隊內部進行權衡選擇。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM