---
# System prepended metadata

title: 【學習筆記】Git rebase
tags: [git]

---

# Git rebase
[Documentation](https://git-scm.com/docs/git-rebase)
> ### Name
> git-rebase - Reapply commits on top of another base tip
> ### SYNOPSIS
> ```
> git rebase [-i | --interactive] [<options>] [--exec <cmd>]
>	[--onto <newbase> | --keep-base] [<upstream> [<branch>]]
> git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]
>	--root [<branch>]
> git rebase (--continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)
> ```

```reabse``` 翻成中文大概是「重新定義分支的參考基準」。

假設我們現在在```topic``` branch上:
```
          A---B---C topic/HEAD
         /
    D---E---F---G master
```
輸入下列指令後:
```
git rebase master
git rebase master topic
```
歷史紀錄會變成這樣:
```
                  A'--B'--C' topic/HEAD
                 /
    D---E---F---G master
```
看起來像是把 A、B、C 從 E 上面，剪下貼上到 G 上面，
不過實際上是這樣:
```
           A---B---C
          /       A'--B'--C' topic/HEAD
         /       /
    D---E---F---G master
```
A'、B'、C'是新創建的 commit，SHA-1與舊的 A、B、C commit都會不一樣。
而舊的 A、B、C commit 仍然存在，並未被刪除，
不過因為已經沒有 branch 指向它，所以沒有顯示出來，
就在那邊等待 Git 的資源回收機制處理他們。

不過因為```rebase```等於是修改歷史，
所以不應該將已經```push```出去的內容任意進行```rebase```，
不然可能會造成團隊協作的困擾。
    
我個人比較常用的應用是修改還未```push```上去的 commit message，
有時候可能已經 commit 很多了，
但發現中間的 commit message 需要修改:
```
 • "commit 5" (HEAD)
 ◦ "commit 4"
 ◦ "commi 3"
 ◦ "commit 2"
 ◦ "commit 1"
```
這時候只要使用```rebase```:
```
git reabse -i HEAD~3 
```
```-i```是```--interactive```的縮寫，指將 commit 列出，讓使用者可以在```rebase```前進行修改。
> ```-i```
> ```--interactive```
> Make a list of the commits which are about to be rebased.    Let the user edit that list before rebasing.
    
會出現:
```
pick xxxxxxxx commit 5
pick xxxxxxxx commit 4
pick xxxxxxxx commi 3

# Rebase xxxxxxxx..xxxxxxxx onto xxxxxxxx (3 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
```
這時候我們按照提示，使用 vim 指令```i```(指INSERTr)，將 "pick" 改成 "r"或"reword":
```
pick xxxxxxxx commit 5
pick xxxxxxxx commit 4
reword xxxxxxxx commi 3
```
再使用vim指令```ESC :wq Enter```，就可以修改 commit message 了。

## 參考資料
https://git-scm.com/docs/git-rebase
https://medium.com/%E7%A8%8B%E5%BC%8F%E4%B9%BE%E8%B2%A8/git-rebase-%E4%BD%BF%E7%94%A8%E5%A0%B4%E6%99%AF-604d753e53f6
https://gitbook.tw/chapters/branch/merge-with-rebase