圖解Git命令(一)

在這裏插入圖片描述

Merge

多分支模式可以將每個人所做的新的更改分離開來,極大地方便了項目管理,避免了未經評審或壞的更改進入項目。一旦評審通過,則可以將這些更改合併到項目中。

將一個分支的更改添加到另一個分支的一種方式是 git merge。Git 有兩種合併的執行方式,分別是 fast-forwardno-fast-forward

現在你可能還不能理解這些,所以讓我們一起來看看它們的差異。

Fast-forward (--ff)

如果當前分支與即將合併的分支之間沒有額外的提交,將採用 fast-forward 的合併方式。Git 很懶,所以默認使用 fast-forward 方式處理分支合併。這種合併方式不會創建新的提交,而是直接在當前分支中合併提交,且當舊分支被移除後,其分支信息也會被一併刪除。

在這裏插入圖片描述

完美!現在 dev 分支上的所有更改都被合併到 master 分支。那麼,no-fast-forward 有什麼不同呢?

No-fast-foward (--no-ff)

如果當前分支與即將合併的分支之間沒有額外的提交,那是相當的好。然而,這種情況很少。如果當前分支有待合併分支上所沒有的提交更改,Git 將使用 no-fast-forward 合併方式。

執行 no-fast-forward 合併,Git 將在活動分支上創建一個新的提交,這個新的提交會同時指向活動分支和我們要合併的分支。

在這裏插入圖片描述

沒什麼大不了的,又是一個完美的合併!現在 master 分支已經包含了 dev 分支的所有更改了。

Merge Conflicts

儘管 Git 擅長決定如何合併分支並向文件中添加更改,但也不是所有情況都能作出決定。比如我們想合併的兩個分支都修改了同一個文件的相同行,或者一個分支刪除了文件,但另一個分支卻修改這個文件。

這種情況,Git 會詢問你來決定應該保留哪個修改。舉個例子,假如我們在兩個分支中同時修改了 README.md 文件中的第一行。

在這裏插入圖片描述

現在你想將 dev 分支合併到 master 分支,將會出現合併衝突:would you like the title to be Hello! or Hey!?

Git 會找出衝突發生的位置,爲了解決合併衝突,我們需要手動刪除不想保留的更改,保存並重新添加文件,然後再提交更改。

在這裏插入圖片描述

耶!儘管解決合併衝突很煩人,但這是有意義的,因爲 Git 不會幫我們去假設需要保留哪些更改。

Rebase

我們知道使用 git merge 可以將一個分支的更改添加到另一個分支。除了這種方式,我們還可以使用 git rebase 命令來完成這個工作。

git rebase 命令將複製當前分支的所有提交,並將它們移動到指定分支上。

在這裏插入圖片描述

完美!我們現在可以在 dev 分支上使用 master 分支上進行的所有更改了。

與 merge 最大不同的是,rebase 總是保留當前分支的最新更改,不會嘗試尋找哪些文件需要保留,哪些不需要。因此你不需要處理合並衝突,同時也會保持線性的 git 提交歷史。

上面的例子展示了在 rebase master 分支的動作,但這裏有一個大問題,導致我們通常不想這麼處理。因爲 git rebase 複製提交時會產生新的哈希值,從而影響了項目的提交歷史。

當你在 feature 分支上工作時,並且 master 分支已經更新了,那麼使用 rebase 是非常合適的。因爲你可以在分支上獲取所有更新,防止將來合併時發生衝突。

交互式 Rebase

在 rebase 提交之前,我們還可以通過交互式 rebase 對提交進行修改。當你想修改正在使用的分支上的某些提交時,交互式 rebase 就非常有用。

我們可以對 rebase 的提交進行六種操作:

  • reword: 修改提交附帶消息
  • edit: 修改提交
  • squash: 將提交合併到上一個提交中
  • fixup: 將提交合併到上一個提交中,並且不保留提交的日誌消息
  • exec: 在我們 rebase 的每一個提交的基礎上運行命令
  • drop: 刪除提交

太棒了!這樣,我們就可以完全控制提交。如果想刪除提交,就可以 drop 它。

在這裏插入圖片描述

或者,我們要壓縮多個提交以獲得更清晰的歷史記錄,那也沒問題!

在這裏插入圖片描述

使用交互式 rebase,你可以對要 rebase 的提交有更多控制,即使是在當前活動分支。

Reset

有時候我們提交了更改,但是因爲一些原因不想要了。比如這是一個 WIP(Work In Process)提交,或者這個提交有 Bug。那麼,我們就可以使用 git reset 對分支進行重置。

git reset 會刪除所有當前暫存的文件,並讓我們控制 HEAD 指向的位置。

Soft reset

soft reset 將 HEAD 移動到指定的提交,不會丟棄該提交之後引入的更改。

假如我們不想保留添加了 styles.css 文件的 9e78i 提交,也不想保留添加 index.js 文件的 035cc 提交。但是,我們想保留 styles.css 和 index.js 文件,那麼使用 soft reset 就非常合適。

在這裏插入圖片描述

執行 git status 可以看到我們仍然可以訪問先前提交所做的更改,即 styles.css 和 index.js 文件。這很棒,意味着我們可以修復這些文件的內容,後續再次提交。

Hard reset

有時候,我們不想保留某個提交引入的更改,不像 soft reset,我們不再需要訪問它們了。Git 允許將其 reset 到指定的提交狀態,包括工作目錄和暫存文件都會被重置。

在這裏插入圖片描述

比如這裏 Git 丟棄了 9e78i035cc 提交引入的更改,並將其狀態重置爲 ec5be 提交時的狀態。

Revert

撤銷更改的另一種方法是執行 git revert。通過還原某個提交,我們創建一個包含還原更改的新提交。

假如 ec5be 添加了 index.js 文件,後來我們意識到我們不再希望此提交引入此更改!於是,我們需要還原 ec5bc 提交。

在這裏插入圖片描述

完美!9e78i 提交還原了 ec5be 提交引入的更改。執行 git revert 對於撤銷特定提交而不修改分支的歷史記錄非常有用。

Cherry-Pick

當某個分支中的提交包含了當前活動分支需要更改時,可以使用 cherry-pick 命令。cherry-pick 一個提交時,會在活動分支上創建一個新的提交,其中包含了 cherry-pick 提交引入的更改。

假如 dev 分支的 76d12 提交在 index.js 文件添加了更改,而 master 分支剛好需要這些更改。但是 master 關心的只是這個提交,並不關心整個 dev 分支。

在這裏插入圖片描述

酷!現在 master 分支就包含了 76d12 提交的更改了。

Fetch

如果我麼有一個遠程 Git 分支,例如 GitHub 上的一個分支,則可能該遠程分支具有當前分支所沒有的提交!這也許是由於另一個分支被合併到遠程分支了,或者你的小夥伴提出了一個解決方案。

我們可以通過 git fetch 將遠程分支的更改拉取到本地。fetch 操作只會下載新數據,並不會影響本地分支。

在這裏插入圖片描述

現在,我們可以看到自上次推送以來遠程分支上所做的更改。本地已經擁有新數據了,接下來我們可以決定要如何處理這些數據。

Pull

儘管 git fetch 對於獲取分支的遠程信息非常有用,但是我們也可以執行 git pullgit pull 實際上是 git fetchgit merge 兩個命令的組合。當我們從遠程分支 pull 更改時,實際上首先需要像 git fetch 那樣拉取數據,之後將最新的更改自動合併到本地分支中。

在這裏插入圖片描述

太棒了!我們現在可以與遠程分支完美同步,並具有所有最新的更改!

Reflog

每個人都會犯錯,這是 OK 的!有時候,你可能覺得自己已經把 git 倉庫搞砸了,以致於只想完全刪除它。

git reflog 是一個非常有用的命令,用於顯示所有已執行動作的日誌。包括 merge、reset、revert 等等對分支的任何更改操作。

在這裏插入圖片描述

如果你輸入有誤,可以先重置 HEAD,然後再根據 reflog 的信息輕鬆地重做。

假如,我們不想合併 origin 分支。我們執行 git reflog 命令,看到合併前的狀態是 HEAD@{1},於是我們通過 git resetHEAD 指向 HEAD@{1}

在這裏插入圖片描述

可以看到,最新的操作已經被記錄到日誌 😊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章