# 合併多個 Commit , 編輯

## Commit Merge 模式

***

* **Merge commit**: 保留 Branch commit 歷程，又稱為 **no fast-forward merge**。(預設的 Merge 模式)<br>
* **Squash merge**: 忽略並壓縮 Branch commit 歷程。<br>
* **Rebase merge (基底合併)**: 將 Branch commit 歷程加入到 Main branch commit，又稱為 **fast-forward merge** 。(從 Branch 取得最新內容，並重新定位 Commit 基準)<br>
* **Cherry-Pick (揀選)**: 從一個 Branch 中獲取單個 Commit 並將其 Merge 於另一個 Branch。

<div><figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2F0NuXENpw42Y6FxEbnW67%2F3GuQE.png?alt=media&#x26;token=288ea2ef-15d5-4251-a4de-3940ca5cc8d6" alt=""><figcaption><p>Merge commit</p></figcaption></figure> <figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2F1tuXfWj1fhtvzOvWyZGO%2FLh9LK.png?alt=media&#x26;token=17226930-0be9-4c5e-b63f-c0278e52a631" alt=""><figcaption><p>Squash merge</p></figcaption></figure></div>

<div><figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2FXmhHJnyGnlexFuRCegN8%2FPasted%20image%2020230515022718.png?alt=media&#x26;token=10168aaa-1637-4e0b-87c3-17e8a90efdd5" alt=""><figcaption><p>Rebase commit</p></figcaption></figure> <figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2FxDWMQ6PVZe9VCOb9OuiA%2FPasted%20image%2020230515022457.png?alt=media&#x26;token=f7df71f4-69e5-4b71-b7ad-ed927305b7f8" alt=""><figcaption><p>Cherry-Pick</p></figcaption></figure></div>

**將 Merge commit (Branch merge) 到當前 Branch。**

{% code title="SHELL" overflow="wrap" %}

```powershell
git merge <要合併的 Branch>
```

{% endcode %}

**執行 Rebase merge 到當前 Branch。。**

{% code title="SHELL" overflow="wrap" %}

```powershell
git rebase <Branch 名稱>
```

{% endcode %}

{% hint style="success" %}
**當有多位開發者時，經常將 Remote main branch 合併到本地功能性 Branch，能盡早發現衝突。**
{% endhint %}

**執行 Cherry-pick 到當前 Branch。。**

{% code title="SHELL" overflow="wrap" %}

```powershell
git cherry-pick <Git SHA-1 ID>
```

{% endcode %}

{% hint style="info" %}
**同一 Repository 的 Git SHA-1 ID 不會重複。**
{% endhint %}

## Interactive rebase

***

Interactive rebase 允許以互動的方式(interactive)修改、刪除、合併和拆分同一 Branch 的 Commit。

Interactive rebase 是一個強大的工具，但應該小心使用它，因為它可以改變 Branch 的歷史，這可能會給在同一 Branch 上工作的其他開發人員帶來問題。通常建議只在本地 Branch 或尚未 Push branch 上使用 Interactive rebase。

1. **執行 Interactive rebase ，顯示編輯介面。** (使用預設編輯器開啟)

{% code title="SHELL" overflow="wrap" %}

```powershell
git rebase -i HEAD~7
git rebase -i HEAD~<顯示 Commit 數量>
```

{% endcode %}

{% hint style="success" %}
**`git log` 由新到舊(上到下)顯示；`git rebase -i` 由舊到新(上到下)顯示，並且不會顯示 Commit 日期。**
{% endhint %}

<details>

<summary>Interactive rebase 編輯說明</summary>

`<Commands> <Git SHA-1 ID> <Commit 摘要>` , 常用的 `<Commands>`:&#x20;

**pick**: Commit 維持不變

**squash**: 將此條 Commit 併入前一條 Commit。&#x20;

**drop**: 刪除 Commit。&#x20;

**reword**: 編輯 Commit。&#x20;

**label**: 使用標籤標記 Commit。

</details>

<div><figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2Fa2isjfbTc6LbK30q5OPn%2FPasted%20image%2020230515042254.png?alt=media&#x26;token=3f6b81be-ba57-4568-8cda-d7770e2e53ac" alt="" width="375"><figcaption><p>編輯介面</p></figcaption></figure> <figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2FGKzSzhtY1tJ0LgDakd6h%2FPasted%20image%2020230515043638.png?alt=media&#x26;token=9bd052a9-8633-4c69-ae16-26cec88bae7b" alt="" width="375"><figcaption><p>使用 squash 後，壓縮的訊息</p></figcaption></figure> <figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2FwcQLwT7BRSKddCyqSaDV%2FPasted%20image%2020230515195720.png?alt=media&#x26;token=dd387351-6116-483e-93f4-5ec3572fdb6a" alt="" width="375"><figcaption><p>使用 squash 後，log 訊息</p></figcaption></figure></div>

**跳過 Conflict commit。**

{% code title="SHELL" overflow="wrap" %}

```powershell
git rebase --skip
```

{% endcode %}

**繼續因Conflict 而暫停的 Interactive rebase。**

{% code title="SHELL" overflow="wrap" %}

```powershell
git rebase --continue
```

{% endcode %}

## 製作 Remote repository 副本

***

1. **建立空白的 Remote repository 副本。**

**可以 clone URL** 或 **建立空白副本**。

<div><figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2FXwCMrO7AOKchgmFwzXm0%2FPasted%20image%2020230516224313.png?alt=media&#x26;token=63493704-9cc6-41ab-886e-b1a653002dce" alt=""><figcaption><p>導入 Repository</p></figcaption></figure> <figure><img src="https://3293907157-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtlnsDqWTGrgKWvoywdfm%2Fuploads%2FNOTzFJ7tUmXbWE6PqkcL%2FPasted%20image%2020230516224754.png?alt=media&#x26;token=5b999042-b171-4bba-816e-6f2a176045ba" alt=""><figcaption><p>建立空白 Repository</p></figcaption></figure></div>

2. **Push 所有 Tags、本地 Branchs。**

{% code title="SHELL" overflow="wrap" %}

```powershell
git push --mirror <Github網址>.git
```

{% endcode %}

{% hint style="warning" %}
**此命令會對 Remote repository 產生重大影響，因為它會更新或創建 Branchs 和 tags。因此，應謹慎使用並且擁有的必要權限。**
{% endhint %}

## 參考資料

***

[Windows 上的 Git：如何設置合併工具？ - 堆棧溢出](https://stackoverflow.com/questions/426026/git-on-windows-how-do-you-set-up-a-mergetool)

[git - merge --squash 和 rebase 有什麼區別？ - 堆棧溢出](https://stackoverflow.com/questions/2427238/what-is-the-difference-between-merge-squash-and-rebase)

[Git Rebase VS Merge VS Squash：如何選擇合適的？ - 開發社區](https://dev.to/devsatasurion/git-rebase-vs-merge-vs-squash-how-to-choose-the-right-one-3a33)

[合併策略和壓縮合併 - Azure Repos | Microsoft Learn](https://learn.microsoft.com/zh-tw/azure/devops/repos/git/merging-with-squash?view=azure-devops)

[About pull request merges - GitHub Docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges)

[Git fast-forward VS no fast-forward merge - Stack Overflow](https://stackoverflow.com/questions/6701292/git-fast-forward-vs-no-fast-forward-merge)
