文章轉發自專業的Laravel開發者社區,原始連接: https://learnku.com/laravel/t...
提交是 Git 倉庫的重要組成部分之一,不只於此,提交信息 貫穿於 Git 倉庫的整個生命週期。隨着項目/倉庫的發展(新特性的增長、Bugs 的修復、架構的重構),提交信息可讓咱們看到改了什麼地方以及是如何改動的。所以,這些信息以一種簡短、精確的方式反映着潛在的變化是很是重要的。css
Git 提交消息就像是你在你接觸過的代碼上面留下的指紋。任何你今天提交的代碼,一年之後當你看到這段代碼的變化時,你將感謝本身當時留下的清晰、有意義的提交信息,同時它還將使你的開發變得更爲容易。當提交被基於上下文獨立時,由某個提交引入的 Bug 將會更快被找到,而且更容易恢復到致使錯誤提交前的代碼。html
當你工做在一個大的項目中時,咱們常常更新、新增或者移動文件。確保在這種狀況下維持提交消息將很棘手,尤爲是在開發週期跨越數天,數週甚至數月的狀況下。所以,爲了簡化維護簡潔提交歷史記錄的工做,這篇文章將使用開發人員在處理 Git 倉庫時可能遇到的一些常見狀況。前端
在咱們深刻討論以前讓咱們快速的瞭解一下,在咱們假設的 Ruby 應用程序中,典型的開發工做流是什麼樣子的。laravel
注意: 這篇文章假定您瞭解基本的 Git 知識 、分支的工做方式、如何在階段中添加未提交的分支更改以及如何提交更改。若是你不瞭解這些流程, 咱們的文檔 是一個很好的起點。git
如今,咱們正在開發一個小型的 Ruby on Rails 項目。咱們須要在首頁添加一個導航視圖,這涉及到更新和添加幾個文件。下面是整個流程的逐步細分:shell
application_controller.rb
index.html.haml
_navigation.html.haml
styles.css.scss
新功能已經準備好全部指望的修改,該更新測試文件了;要更新的文件以下:後端
application_controller_spec.rb
navigation_spec.rb
由於全部的文件分屬於架構的不一樣區域,因此咱們對這些更改彼此隔離進行提交,確保每次提交表明一個特定的上下文,並按順序提交。我一般喜歡從後端 -> 前段
的順序。首先提交大多數之後端爲中心的更改,接着是中間層,最後是在提交列表中之前端爲中心的更改。安全
application_controller.rb
& application_controller_spec.rb
;Add routes for navigation。_navigation.html.haml
& navigation_spec.rb
;Page Navigation View。index.html.haml
;Render navigation partial。styles.css.scss
;Add styles for navigation。如今咱們已經提交了更改,咱們使用分支來建立 merge 請求。一旦建立了 merge 請求,一般會在更改合併進 master
分支以前由原倉庫的擁有者進行審覈。如今咱們來了解一下,在代碼審覈期間咱們可能會面臨的不一樣狀況。架構
想象一下,審閱者查看了styles.css.scss
文件並建議進行更改。在這種情形下,進行更改很是簡單,由於對樣式的更改是你分支上 最近一次 提交的一部分。下面是咱們怎樣處理此次更改的步驟:app
styles.css.scss
文件作必要的更改。git add styles.css.scss
。當這些改變被暫存以後,咱們須要將這些更改 添加 到上次的提交中;運行 git commit --amend
。
git commit
命令 修改 暫存區中的最近一次提交。因爲你修改了現有的提交,因此必須使用git push --force-with-lease <remote_name> <branch_name>
將這些更改 強制推送 到你的遠程倉庫。這個命令將會使用咱們在本次倉庫更新後的提交,覆蓋遠程倉庫上消息爲Add styles for navigation
的那次提交。
在強制推送分支時須要注意的一件事是,若是你和其餘同事工做於同一分支,當其餘人嘗試向一個剛被強制推送過的遠程分支正常推送他們的更改時,可能遇到一些麻煩。因此,請明智地使用強制推送。你能夠在 這裏 瞭解有關 Git 強制推送的更多選項。
在以前的狀況下,因爲咱們只能修改最後一次提交,因此這種修復很是簡單,可是想象一下,若是審稿人建議改變_navigation.html.haml
。 在這種狀況下,由於它是第二次從頂部提交,因此要想改變它不會像第一種狀況那樣直接。讓咱們仍是來看看如何處理這個問題吧:
每當在分支中進行提交時,它就被惟一的SHA1哈希字符串標識。把它看做是一個惟一的ID,它將一個提交與另外一個提交分開。經過運行git log
,您能夠查看分支中的全部提交以及它們的SHA1哈希。經過它,你會看到一個看起來有點相似下面這樣的輸出,其中最近的提交在頂部;
commit aa0a35a867ed2094da60042062e8f3d6000e3952 (HEAD -> add-page-navigation) Author: Kushal Pandya <kushal@gitlab.com> Date: Wed May 2 15:24:02 2018 +0530 Add styles for navigation commit c22a3fa0c5cdc175f2b8232b9704079d27c619d0 Author: Kushal Pandya <kushal@gitlab.com> Date: Wed May 2 08:42:52 2018 +0000 Render navigation partial commit 4155df1cdc7be01c98b0773497ff65c22ba1549f Author: Kushal Pandya <kushal@gitlab.com> Date: Wed May 2 08:42:51 2018 +0000 Page Navigation View commit 8d74af102941aa0b51e1a35b8ad731284e4b5a20 Author: Kushal Pandya <kushal@gitlab.com> Date: Wed May 2 08:12:20 2018 +0000 Add routes for navigation
這就是 Git ReBase
命令發揮做用的地方。每當咱們但願編輯 git ReBase
的特定提交時,咱們須要先將咱們的分支從新定位爲在咱們但願編輯的提交以前,將頭移到右邊。在咱們用例中,咱們須要更改讀取的提交 Page Navigation View
。
這裏請注意,正確的提交哈希是咱們想要修改提交的前一個提交哈希;拷貝那個哈希,而後執行下面的步驟:
變基(rebase)分支,移動到目標提交的前一次提交;運行git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20
rebase
命令的 交互 模式,並提供了要變基的提交哈希。pick 4155df1cdc7 Page Navigation View pick c22a3fa0c5c Render navigation partial pick aa0a35a867e Add styles for navigation # 在 8d74af10294 上變基 8d74af10294..aa0a35a867e 範圍(3次提交) # # 命令: # p, pick = 保留本次提交 # r, reword = 保留本次提交,但要修改提交消息 # e, edit = 保留本次提交,但暫停下來進行修改(不僅修改提交消息) # s, squash = 保留本次提交,但合併到前一次提交 # f, fixup = 與「squash」相似,但丟棄本次提交消息 # x, exec = 運行 shell 命令(本行的剩餘內容) # d, drop = 刪除本次提交 # # 這些行能夠重排順序,並自頂向底依次執行。 # # 若是你刪除一行,那次提交將會丟失。 # # 若是你刪除全部行,本次變基(rebase)將會停止。 # # 注意空提交已註釋掉。
注意每一個提交前面都有一個單詞pick
,下面的註釋是咱們可能用到的關鍵字。由於咱們想要 編輯 某此提交(4155df),因此須要把pick 4155df1cdc7 Page Navigation View
改爲edit 4155df1cdc7 Page Navigation View
。保存修改,而後退出編輯器。
如今你的分支就重置到了所作的修改包含_navigation.html.haml
的時刻。打開文件根據審覈反饋執行須要的修改。一旦修改完畢,經過運行git add _navigation.html.haml
命令進行暫存。
既然咱們暫存了這些改變,如今是時候把 HEAD 分支移回咱們的原始提交了(包含咱們添加的最新修改),運行git rebase --continue
,這將會在終端打開你的默認編輯器而後顯示在變基(rebase)期間的提交消息;Page Navigation View
。若是但願的話,你能夠改變這個提交消息,可是咱們如今讓它保持現狀,保存並退出編輯器。此刻,Git 會從新播放你所編輯的提交以後的全部提交,而且如今的HEAD
分支回溯到了咱們原始的頂部提交。
因爲咱們再次修改了遠程倉庫中已存在的一次提交,因此須要使用git push --force-with-lease <remote_name> <branch_name>
強制推送分支。
一個很常見的場景就是爲了修復以前提交的內容,你已經 commit 了幾回。如今咱們來儘量地減小 commit 的次數並把它們和原來的提交合並起來。
你須要作的就是就像你在其餘場景同樣啓動交互式 rebase。
pick 4155df1cdc7 Page Navigation View pick c22a3fa0c5c Render navigation partial pick aa0a35a867e Add styles for navigation pick 62e858a322 Fix a typo pick 5c25eb48c8 Ops another fix pick 7f0718efe9 Fix 2 pick f0ffc19ef7 Argh Another fix!
假設你如今想要把這些提交記錄都合併到 c22a3fa0c5c Render navigation partial
。你只須要作到:
pick
改成 squash
或者 fixup
。注意: squash
保留了描述中的提交註釋。 fixup
不會保留提交的註釋而只保留原始註釋。
你會獲得這樣的結果:
pick 4155df1cdc7 Page Navigation View pick c22a3fa0c5c Render navigation partial fixup 62e858a322 Fix a typo fixup 5c25eb48c8 Ops another fix fixup 7f0718efe9 Fix 2 fixup f0ffc19ef7 Argh Another fix! pick aa0a35a867e Add styles for navigation
保存更改,退出編輯,你就完成了!這是產生的歷史:
pick 4155df1cdc7 Page Navigation View pick 96373c0bcf Render navigation partial pick aa0a35a867e Add styles for navigation
和之前同樣,你要作的就是 git push --force-with-lease <remote_name> <branch_name>
,改變就生效了。
若是你想要徹底地刪除一個提交,把 squash
或者 fixup
換成 drop
或者乾脆刪掉那一行。
爲了不衝突,請確保你移動到的目標沒有編輯到同一個文件。
pick 4155df1cdc7 Page Navigation View pick c22a3fa0c5c Render navigation partial fixup 62e858a322 Fix a typo # this changes styles.css fixup 5c25eb48c8 Ops another fix # this changes image/logo.svg fixup 7f0718efe9 Fix 2 # this changes styles.css fixup f0ffc19ef7 Argh Another fix! # this changes styles.css pick aa0a35a867e Add styles for navigation # this changes index.html (no conflict)
fixup
若是你清楚知道你將 fixup 哪個提交,你不須要浪費時間構思一個臨時的名稱,如: "Fix 1", "Fix 2", ..., "Fix 42"。你可使用如下的方法:
第一步:開始使用 --fixup
在你 stage
而且修復了你想要的內容時,使用如下命令:
git commit --fixup c22a3fa0c5c
(注意這個 hash 信息對應 c22a3fa0c5c Render navigation partial
)
以上命令會生成一個 commit:: fixup! Render navigation partial
.
第二步:召喚你的好朋友 --autosquash
簡單的交互性 rebase,如下命令會讓 git
在正確的位置裏設置 fixup
:
git rebase -i 4155df1cdc7 --autosquash
如今你的歷史是:
pick 4155df1cdc7 Page Navigation View pick c22a3fa0c5c Render navigation partial fixup 62e858a322 Fix a typo fixup 5c25eb48c8 Ops another fix fixup 7f0718efe9 Fix 2 fixup f0ffc19ef7 Argh Another fix! pick aa0a35a867e Add styles for navigation
你還可使用 git rebase --autosquash
命令來直接跳過 review 階段,可是通常建議除非你感受特別安全,不然仍是少用爲妙,由於你沒機會 review 到具體變動。
若是你在開發一個大功能,有時候你在分支裏(如:add-page-navigation
)留下不少 commit ,而你不喜歡讓這些 commit 進入主分支,接下來我教你一個方法:
master
分支衝突;add-page-navigation
分支下時,可使用 git rebase master
或者 git merge master
命令來保持與 master
的更新; 接下來使用命令建立補丁文件 git diff master add-page-navigation > ~/add_page_navigation.patch
master
分支和 add-page-navigation
分支作了一個 diff 操做,而且將結果輸出到 ~/add_page_navigation.patch
文件中。git checkout master
切換到 master
分支上;git branch -D add-page-navigation
刪除本地分支 add-page-navigation
(咱們已經有補丁文件了,不要懼怕);git checkout -b add-page-navigation
建立一個新的分支;add-page-navigation
分支上,此分支沒有任何更改;git apply ~/add_page_navigation.patch
來應用補丁裏的修改;未提交
的狀態顯示着;就跟以前遇到的場景同樣,咱們修改了整個分支,你須要作一個 force push 了。
儘管咱們已經介紹了使用 Git 進行平常工做流程中出現的大多數常見的狀況,但重寫 Git 歷史是一個巨大的話題,而且當你在熟悉上述提示時,你能夠在 Git 官方文檔 學習圍繞該主題的更高級概念。祝你愉快的學習 Git。