# git rebase 用法

git rabase（变基）常用三个功能：

* 分支合并
* 合并commit
* 更改commit信息



1. 合并分支

   原理是将当前分支与要rebase的分支进行比较，找到两条分支的共同节点，然后将当前分支变基到master上，并创建一个临时文件c4，然后切换到master分支上，并进行一次merge，此时master和experiment分支都指向了c4，此时可以删除experiment分支。

   ```bash
   $ git checkout experiment
   $ git rebase master
   $ git checkout master
   $ git merge experiment
   ```

![basic-rebase-1.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1656499989054/_F2FI24fC.png align="left" )

![basic-rebase-3.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1656500106015/sy62_DBKz.png align="left")

![basic-rebase-4.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1656500125635/AQUKv96Kt.png align="left")

​	与merge的区别是，merge会创建一个新的merge节点同时指向c3，c4。所以merge会保留c4的commit信息，而rebase在c4'会重新提交包含c3和c4的commit信息。merge更能保存信息，rebase更简洁，保证分支的提交是线性的。

​	merge后分支情况如下：

![basic-rebase-2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1656500134667/NK4HdrJ-u.png align="left")



2. 合并commit

   当前git log如下

   ```bash
   $ git log --graph --oneline
   * 853b82d (HEAD -> test) commit3
   * 3802571 commit2
   * d231bc8 commit1
   ```

   使用git rebase -i 来指定需要合并节点的父节点，如果要合并commit2和commit3，指定commit1的log id，然后自动弹出vim来修改commit（**注意这里的commit的顺序与git log的顺序是相反的！**）。将pick修改为s表示此commit会被上一个commit合并，即新提交的commit合并到旧的commit上。

   ```bash
   $ git rebase -i d231bc8
   
   pick 3802571 commit2
   pick 853b82d commit3
   
   # Rebase d231bc8..853b82d onto d231bc8 (2 commands)
   #
   # Commands:
   # p, pick <commit> = use commit
   ```

   ```bash
   pick 3802571 commit2
   s 853b82d commit3
   
   # Rebase d231bc8..853b82d onto d231bc8 (2 commands)
   #
   # Commands:
   # p, pick <commit> = use commit
   ```

   将pick修改为s后可以修改commit message：

   ```bash
   # This is a combination of 2 commits.
   # This is the 1st commit message:
   
   commit2
   
   # This is the commit message #2:
   
   commit3
   
   # Please enter the commit message for your changes. Lines starting
   # with '#' will be ignored, and an empty message aborts the commit.
   #
   # Date:      Sat Jun 11 13:59:58 2022 +0800
   
   ```

   此时commit3已合并到commit2中

   ```bash
   $ git log --oneline --graph
   * dc30c78 (HEAD -> test) commit2
   * d231bc8 commit1
   ```

   commit2的message如下：

   ```
   commit dc30c78c979b4974ba29c2e17eb2c1787a8bd6f3 (HEAD -> test)
   Author: 
   Date:   Sat Jun 11 13:59:58 2022 +0800
   
       commit2
   
       commit3
   ```



3. 更改commit信息

   commit信息如下，要修改commit2的message，需要使用git rebase -i指定父节点的log ID，在这即commit1的ID

   ```bash
   $ git log --oneline --graph
   * dc30c78 (HEAD -> test) commit2
   * d231bc8 commit1
   ```

   commit2的message如下：

   ```
   commit dc30c78c979b4974ba29c2e17eb2c1787a8bd6f3 (HEAD -> test)
   Author: 
   Date:   Sat Jun 11 13:59:58 2022 +0800
   
       commit2
   
       commit3
   ```

   ```bash
   $ git rebase -i d231bc8
   ```

   vim将pick修改为r修改提交信息

   ```
   pick dc30c78 commit2
   
   # Rebase d231bc8..dc30c78 onto d231bc8 (1 command)
   #
   ```

   ```
   s dc30c78 commit2
   
   # Rebase d231bc8..dc30c78 onto d231bc8 (1 command)
   #
   ```

   将commit2和commit3修改到一行上

   ```bash
   commit2 commit3
   
   # Please enter the commit message for your changes. Lines starting
   # with '#' will be ignored, and an empty message aborts the commit.
   #
   # Date:      Sat Jun 11 13:59:58 2022 +0800
   ```

   git log 查看commit2的message

   ```bash
   commit c6e822ac8d84d17da4668b530667573c345dccf7 (HEAD -> test)
   Author: 
   Date:   Sat Jun 11 13:59:58 2022 +0800
   
       commit2 commit3
   
   ```

其中 pick , s , r 参数的含义如下：

![5f5a79a5d2bde029d4de9d98026ef3f2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1656500189279/mTf8qdpA1.png align="left")



