學習如何使用 Git 來壓扁、變基和精選
當我與別人談到 Git 時,幾乎每個人都對 git rebase 有強烈的印象,這個 讓許多人遇到了問題,而不得不更改目錄、刪除倉庫、然後再重新克隆一個倉庫。我認為這是因為他們誤解了分支是如何工作,遇到了一個非常糟糕的預設介面,還有一些合併衝突把事情搞得一團糟。
如果你曾在本地的倉庫提交過很多次,並希望能把這些提交都合併為一個提交,接下來,我們就來介紹能用什麼 Git 命令達到這個目的。Git 稱這個概念為 “壓扁提交squash commits”。我在編寫文件時發現了這個概念:我花了十幾個提交才修改好我的 Markdown 文件,但是倉庫的維護者不想看到我的所有嘗試,以免擾亂了該專案的歷史,所以我被告知“需要壓扁你的提交”。
壓扁提交聽起來是一個很有用的方法。但是隻有一個問題:我不知道該怎麼做。作為 Git 的新手,我做了任何人會做的事情:我去查閱 git-squash 的手冊,但我立即遇到了阻礙:
$ man git-squash > No manual entry for git-squash
我發現沒有一個名為 squash 的 Git 命令,而是被要求 執行一個完全獨立的命令:git rebase 命令,該命令能將我的所有提交最終合併為一個提交。
我知道我碰到一個常見的情形:已經使用工具一段時間的人使用了行話或引用了一個概念,這個概念對他們來說是非常清楚的,但對新手來說就不能明白了。從概念上講,這個情況看起來是這樣的:
我這樣說是為了鼓勵你,你絕對不是第一個或最後一個 被 Git 或談論 Git 的人 弄糊塗的人。你可以要求對方說明白他的意見,並幫助你應該使用的正確命令。倉庫的維護者實際上的意思是,“使用 git rebase 命令**,將很多提交壓扁成一個提交”。
git rebase 命令會將一個提交鏈從其第一個父級中刪除,並將其放置在另一個提交鏈的末尾,將兩個提交鏈組合成一個長鏈,而不是兩個並行鏈。我意識到這是一個很複雜的定義。
回想一下 Git 的提交是如何連結在一起的,你可以看到,除了初始的 main(或 master)分支外,任何分支都有一個 父提交parent commit 作為該鏈的 “基礎base”。“變基rebase” 能使另一個鏈中的最後一個提交成為指定分支的新 “基礎提交base commit”。
在 Git 中整合來自不同分支的修改主要有兩種方法:合併merge 以及 變基rebase,你可能更熟悉 git merge 命令。接下來,就來看看 [git-scm.com] 是如何解釋 git merge 和 git rebase 的差異:
在合併示例中,它會把兩個分支的最新快照(C3 和 C4)以及二者最近的共同祖先(C2)進行三方合併,合併的結果是生成一個新的快照(C5)。experiment 的分支指標仍然存在,仍然指向 C4。
在變基示例中,它提取在 C4 中引入的補丁和修改,然後在 C3 的基礎上應用一次,使 C3 成為 C4 的新父級,併產生了一個名為 C4' 的新提交。
(LCTT 譯註:具體的命令如下:
$ git checkout experiment $ git rebase main First, rewinding head to replay your work on top of it... Applying: added staged command
它的原理是首先找到這兩個分支 —— 即當前分支 experiment、變基操作的目標基底分支 main —— 的最近共同祖先 C2,然後對比當前分支相對於該祖先的歷次提交,提取相應的修改並存為臨時檔案,然後將當前分支指向目標基底 C3,最後以此將之前另存為臨時檔案的修改依序應用。)
值得注意的是,分支指標 main 沒有移動。要讓 Git 將指標移動到鏈的末尾(由experiment 指向),你還需要執行合併。
(LCTT 譯註:具體的命令如下:
$ git checkout main $ git merge experiment
此時,C4' 指向的快照就和上面使用 merge 命令的例子中 C5 指向的快照一模一樣了。)
git rebase 並不能替代 git merge。git rebase 是一種用於製作更清晰的歷史記錄,以與 git merge 結合使用的工具。
(LCTT 譯註:使用 git rebase 命令將提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一樣。)
互動式變基能給你一個更友好的介面!
從命令列執行 git rebase 命令,最可怕的地方在於它糟糕的預設介面。執行命令 git rebase 要麼有效,要麼會變得一團糟,因為它沒有太多的反饋或方法來確保它做你想做的事情。幸運的是,git rebase 命令和許多其他 Git 命令一樣,具有 互動模式interactive mode,你可以使用引數 -i 或者 -interactive 來使用互動模式。
在使用互動式模式時,git rebase 會從一個糟糕的黑框介面轉換為一個選項選單,允許你選擇對正在變基的提交鏈所做的事。對於每個提交,你可以選擇:
- 選用pick:按原樣包含
- 重寫reword:重寫提交訊息
- 編寫edit:在變基完成之前對提交中的檔案進行進一步更改
- 壓扁squash:將多個提交壓縮成一個提交,保留所有提交訊息
- 修理fixup:將多個提交壓縮成一個提交,但只保留最後一個提交訊息
- 丟棄drop:丟棄此提交
就我個人而言,我更喜歡 VS Code 的開源 GitLens 擴充套件 使用下拉選擇列表佈局選項的方式,但 Git 允許你使用任何編輯器選擇這些選項。對於 Emacs 或 Vim 等純文字工具,你需要鍵入選擇,而不是從選單中選擇,但最終結果仍然是相同的。
知道 何時 做變基與知道 如何 做變基同樣重要。事實上,如果你不在乎你的倉庫歷史提交訊息有點混亂的話,那麼你可以永遠都不使用 git rebase 命令。但是,如果你想要更乾淨的歷史提交訊息,並且想要更少擾亂你的圖形檢視的提交,那麼當你使用 git rebase 命令時,有一個重要的經驗法則需要時刻記住:“不要變基你儲存庫以外的的提交,那些提交可能是別人工作的基礎。”
如果你遵循該準則,不會發生什麼大問題的。
簡而言之,如果你讓一個本地分支來完成你的工作,變基是沒有問題的。但一旦該分支被 推送push 了,就不要再變基該分支了。當然,你想要怎麼做完全取決於你自己。
希望你會認為上述內容有助於你理解 git rebase 命令的工作原理,並能讓你更有信心地使用它。與任何 Git 命令一樣,練習是學習和理解怎麼做的唯一方法。我鼓勵你勇敢地嘗試 互動式變基interactive rebase git rebase -i !
大多數開發人員將修改提交到某一分支上,但是之後發現他們一直提交到了錯誤的分支上。理想情況下,他們可以拿走那個提交,然後把它移到正確的分支,這正是 git cherry-pick 命令的作用。
git cherry-pick 命令利用了變基單個提交的方法。這一用法非常常見,以至於有了它自己的命令。
要使用 git cherry-pick,你只需告訴 Git 你要移動到“那個分支”的提交 ID(由 HEAD 指向):
$ git cherry-pick
如果出現問題,你可以根據 Git 提供的錯誤訊息,來進行恢復:
$ git cherry-pick -i 2bc01cd Auto-merging README.md CONFLICT (content): Merge conflict in README.md error: could not apply 2bc01cd… added EOF lines hint: After resolving the conflicts, mark them with hint: "git add/rm ", then run hint: "git cherry-pick --continue". hint: You can instead skip this commit with "git cherry-pick --skip". hint: To abort and get back to the state before "git cherry-pick", hint: run "git cherry-pick --abort". $ git cherry-pick --abort
git rebase 命令是 Git 實用程式強大的地方之一。你最好在測試倉庫中先練習一下怎麼使用,一旦你熟悉了它的概念和工作流程,你就可以給倉庫一個清晰歷史訊息記錄了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69901823/viewspace-2934849/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- git rebase(變基)—— Git 學習筆記 19Git筆記
- git:rebase(變基)的使用和理解Git
- 【git學習五】git基礎之git分支Git
- 【日報·精選】IBM開源機器學習平臺、深度學習如何改變基因行業IBM機器學習深度學習行業
- 軟體測試學習資源—Git 基礎使用Git
- 【git學習二】git基礎之git管理本地專案Git
- Git的修改提交記錄和變基Git
- git學習之git reflog和git cherry-pickGit
- 【git學習三】git基礎之git管理遠端倉庫Git
- git 和 vim 學習筆記Git筆記
- Git 學習記錄之演變歷史Git
- 【git學習四】git基礎之git為專案打標籤Git
- 學習用工具來駕馭 Git 歷史Git
- [精選]php 如何使用最近很火的ChatGPTPHPChatGPT
- Kubernetes 基礎:首先學習如何使用
- Git和Maven的學習筆記GitMaven筆記
- Git 簡單使用學習筆記Git筆記
- git checkout 和 git reset 的區別 —— Git 學習筆記 09Git筆記
- Shell學習【變數使用】變數
- git學習Git
- Markdown 基礎語法的學習和使用
- java基礎的學習之引數的變化使用Java
- git學習之git rebaseGit
- 精讀《如何在 nodejs 使用環境變數》NodeJS變數
- AIDL使用學習(一):基礎使用學習AI
- 2013年AngularJS學習資源精選AngularJS
- git學習:關於origin和masterGitAST
- 【Git】學習筆記–clone和本地修改Git筆記
- Git(2.14.1版本)學習及使用(一)Git
- Git 的安裝與初次使用 —— Git 學習筆記 03Git筆記
- 如何使用git 生成patch 和打入patchGit
- Shell程式設計基礎學習之三:變數和test程式設計變數
- Android開發 如何使用選擇器(selector) 來實現點選按鈕變色Android
- Pika 1.5王者歸來!將一切壓扁、膨脹、融化、爆炸,化身為了超強特效利器特效
- git的學習Git
- Git學習整理Git
- Git 學習一Git
- git學習地址Git