Git Fast-forward Merge

IMG_20150327_103310

前一陣子,在 twitter 上看到 GitHub 在三月份要來臺灣做教育推廣,剛好中研院資訊所有老師在 03/23 也有邀請 GitHub 來演講。

03/23 當天是 GitHub 員工 John Britton 擔任講者,主要是介紹 Git 、GitHub 使用,自己雖然開發會用 Git 來管理程式碼,但是只對操作上比較熟悉,在整個演講中,又重新了解一些 Git 運作方式,收穫蠻多的,剛好也有人問到一個 Fast-forward 的問題,當下並沒有很清楚了解,因為,演講完之後,有 GitHub 貼紙可以拿,拿到貼紙之後,回到辦公室其實已經忘記了 XD,還好同事有問我知不知道 Fast-forward,立馬在辦公室就找了一下資料。

什麼是 Fast-forward?

簡單來說,Fast-forward 是 git merge 的一種方式,git merge 主要是將不同 branch 中的內容合併到某一個 branch 內。為什麼會特別區分這種方式呢?

用一張圖來解釋:

Fast-foward

Git merge 前

  1. 有一個 master branch,在 master branch 中,已經有了 3 個 commits 了
  2. m3 commit 後,建立了一個 develop branch
  3. develop branch 建立 2 個 commits

目前到這裡,是 git merge 前的操作,而 2 個 branches,分別有 2 個 pointer 指著 branches 的最新 commit 節點。

之後先切換到 master,將 develop branch 合併 (merge) 到 master branch:

develop 合併到 master 後會發現,其實 git 只是將原本指向 m3 commit 節點的指標,移到 d2 ,怎麼會這樣呢?

蠻容易可以了解的,因為 develop branch 建立之後,在 master branch 中並沒有再進行修改(也就是建立新的 commit),所以要把 develop 合併到 master 的話,就是 develop 最新的 commit 的內容了!

反之,develop branch 建立之後,如果 master branch 還有再被修改,之後的合併,就沒辦法使用 fast-forward 來進行合併。

從以下圖可以了解:

cannot-git-fast-forward-detail_sm

  1. 一開始一樣與 Git merge 前所敘述的一樣
  2. develop branch 建立後,在 master branch 中又進行了修改、建立 commits,所以指向 master branch 的指標,已經移到 m5 commit
  3. 接著,要將 develop branch 的內容合併到 master branch 中,此時,會發現無法使用 fast-forward 將指向 master 的指標指向 develop branch 的最新 commit 節點,因為,master branch 已經在建立 develop branch 之後被修改了,所以需要將 develop 的內容與 master 合併之後,建立一個新的 m6 commit

不使用 Fast-forward

也可以在 git merge 的時候,不使用 fast-forward 的方式來進行合併:

No fast-forward

  1. 不使用 fast-forward 的話,把 2 個 branches 內容合併之後,會建立一個新的 m4 commit 節點

如何不使用 fast-forward?

只要在 git merge 指令之後加上 --no-ff 即可:

為什麼不直接使用 fast-forward 要使用這種方式呢?

先來瞭解一下,有沒有 fast-forward,git log 看起來差別在哪:

有 fast-forward (develop 合併到 master 後):

沒 fast-forward (develop 合併到 master 後)

從上面的例子可以看到,如果沒有使用 fast-forward,能知道到哪些 commits 是從其他 branch 合併進來的,而且能在合併的時候加上 commit 訊息。

如果使用 fast-forward 合併,刪除被合併的 branch 後,原本的 commit 會不見嗎?

當然不會,以上面的例子來說,如果 develop branch 合併到 master branch 後,要將 develop branch 刪除,只是會把指向 develop 的指標移除,所以不會讓 develop branch 中的 commits 節點也被移除掉。

Git Fast-forward Merge

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *