實用 Git 中的一些常見錯誤

2021-09-10 03:24:25 字數 3954 閱讀 9208

無論是資料科學家、演算法工程師還是普通開發人員,在每個團隊協作開發任務中,git 都是必不可少的版本控制工具,因此掌握它的基本操作十分有必要。但即便是教程滿天飛的今天,開發人員在使用 git 時也還是會犯一些不應該犯的錯誤。本文總結了其中的幾種常見錯誤,希望能對新手有所幫助。

有時,我們會需要用 force push 把 commit 推送到遠端倉庫。

假設有 2 名開發人員正在合作開發乙個分支

之前開發人員1已經完成更改,把** push 到了遠端倉庫

現在,開發人員 2 也完成了更改,正當他準備提交時,他卻發現自己無法將**推送到遠端倉庫

由於開發人員 2 是個初學者,他 google 了一下,發現了乙個神奇的命令 git push -f,於是進行了強制 push

之後開發人員 1 在檢查遠端倉庫時,發現自己編寫的**全消失了

,使現有**全部丟失。

如果開發人員 2 想避免這個問題,一種理想方法是他先把開發人員 1 的更新從遠端倉庫 pull 到本地,然後把自己的** rebase 一下,再進行 push。這裡我們討論的是在同一分支中從遠端到本地倉庫的 rebase。

git push -f 這個命令非常不安全,除非有絕對的必要,大家最好還是不要用它。它會把本地分支的提交覆蓋遠端推送分支的提交,給協作的同伴帶去不少麻煩,即便是上面的解決方案,它也可能存在乙個時間差的問題,因為你不可能時刻掌握同伴的工作進展。

所以如果大家都用正確的 git 工作流,讓每個開發人員都擁有自己的功能分支,這種情況根本不會發生。

如果你想把乙個分支的修改合併到當前分支,你可以用 git rebase。它和 git merge 的區別是 merge 有乙個合併 commit 的步驟,而 rebase 是把所有 commit 都串聯在一起,讓你本地的分支歷史看起來像沒有經過任何合併一樣。

假設有 2 名開發人員正在合作開發乙個功能分支

開發人員 1 率先完成了一系列 commit,並將其推送到遠端功能分支

之後,開發人員 2 把遠端功能分支的最新更改 pull 到本地

開發人員 2 向本地功能分支新增了一堆 commit

這時,他想把本地倉庫的更新重新 rebase 到遠端倉庫中,於是他把整個預發分支(release branch)在本地功能分支上 rebase 了一下。這裡我們討論的是在不同分支中從遠端到本地倉庫的 rebase

現在,開發人員 2 試著把** push 到遠端功能分支上,由於提交歷史記錄已更改,這個操作不被允許,他只能又開始用 git push -f

最後,當開發人員 1 想從遠端倉庫提取最新**時,由於提交記錄已更改,他被迫需要處理大量**衝突問題

如上圖所示,rebase遠端倉庫會改變提交歷史記錄,並在其他開發人員嘗試從遠端倉庫中提取最新**時產生問題。處理這種情況的理想方法是始終只rebase本地倉庫,本地倉庫中的任何commit都不應該被push到遠端倉庫。

如果別人事先已經把commit推送到遠端功能分支,那麼你最好先用pull命令把更新拉到本地,用merge和你的修改合併,因為merge不會改變提交歷史,而rebase會。

此外,和上個問題一樣,如果使用正確的git工作流,每個開發人員都會有自己的功能分支,這時,開發者在自己的功能分支上進行更新並且在遠端功能分支上做rebase是不會報錯的,因為沒有其他開發人員從同乙個遠端功能分支中提取**。無論如何,盡量避免重新定義遠端倉庫。

rebase是乙個非常強大的功能,使用時也需謹慎。

git amend 命令的作用是修復最近一次 commit,讓你合併你快取區的修改和上一次 commit,而不是提交乙個新的快照。這裡需要注意一點,它不是修改最近一次 commit,而是整個替換掉原 commit,所以對 git 來說這是乙個新的 commit。此外,它還可以用來編輯上一次的 commit 描述。

假設有 2 名開發人員正在合作開發乙個功能分支

開發人員 1 率先完成了 commit,並將其推送到遠端功能分支,我們把它稱為「old commit」

之後,開發人員 2 把最新**從遠端功能分支 pull 到本地功能分支

然後他開始處理本地倉庫中的**,在這個過程中,他沒有向遠端倉庫 push 任何 commit

這時開發人員 1 突然發現之前的 commit 中存在 bug,他用 amend 命令修復了本地倉庫裡的最近一次 commit,我們把它稱為「new commit」

開發人員 1 嘗試把這個新 commit 重新 push 到遠端功能分支,由於提交歷史記錄發生了變化,這個操作報錯了,於是他呼叫了 git push -f

現在,當開發人員 2 想從遠端功能分支中提取最新**時,git 會注意到提交歷史記錄的變化並建立合併的 commit。因此當他 pull 到本地後,他會在本地倉庫裡發現「commit old」和「commit new」,這就破壞了 amend 這個操作的意義。

最後,即便開發人員 2 從遠端分支到本地分支執行 rebase,這個「commit old」還是會出現在本地倉庫中,它仍然會作為歷史提交的一部分。

amend commit 會更改提交歷史記錄,所以當其他開發人員嘗試從遠端倉庫提取最新**時,修改遠端倉庫中的 commit 會產生混淆。

為了避免這個錯誤,最好的方法是只在本地倉庫裡修改 commit,不要對遠端庫里的 commit 做任何修改。當然,一人乙個分支也不會出現這個問題。

git reset 命令是用來將當前 branch 重置到另外乙個 commit 的。它不會產生 commit,而是只更新乙個 branch(branch 本身就是乙個指向乙個 commit 的指標)指向另外乙個 commit。

hard reset 的命令是 git reset --hard

此外,git reset 還有 --soft 和 --mixed,只不過它們都沒有 hard reset 那麼不安全

假設開發人員 1 正在開發乙個功能分支,並在本地倉庫中完成了 5 次 commit

與此同時,他還正在處理尚未提交的兩個檔案

這時,如果他執行了 git reset --hard

那麼功能分支中的最新 commit 會變成是 commit4,commit5 丟失

同時他正在處理的那兩個未提交檔案也會丟失

這時 commit5 還在 git 內部,只不過對它的引用丟失了,我們可以用 git reflog 把它恢復,但總體來說,hard reset 還是很不安全。在 git 中使用 reset 命令時要非常小心,如果必須得用,確保你已經完全評估所有情況。

綜上所述,為了避免使用 git 時出錯,我們可以牢記這幾條教訓:

避免多人在同一分支上協作。上述四個例子中有三個都是在說明這個問題,在日常工作中,遵守正確的工作流非常重要,要確保只有乙個人在乙個功能分支上工作,這是技術主管、高階開發人員尤其需要注意的。

不要到處實用 force push。

如果萬不得已必須使用 force push,先評估其他方案,把它作為最後的手段。

不要試圖修改遠端倉庫裡的 commit,要只在本地倉庫中更改 commit 歷史記錄。但即便是在本地倉庫裡,用 rebase 還是要謹慎。

posted @

2018-12-06 08:40

獨愛公尺粒 閱讀(

...)

編輯收藏

一些git實用操作

將倉庫中的改動同步到本地 在git bash中進入專案目錄下,使用git pull命令 本地有更新,上傳到github倉庫 1 先進入專案資料夾 通過命令 git init 把這個目錄變成git可以管理的倉庫 git init 2 把檔案新增到版本庫中,使用命令 git add 新增到暫存區裡面去,...

Git的一些實用操作

1.使用 git diff 來摺疊多行 用git diff經常會出現很多內容,導致很多內容被遮住了,讓人很是苦惱,幸運的是這裡有個解決方案。如果你使用less作為預設的pager,只需要輸入 s,就可以保證不會被diff刷屏了。或者,你也可以使用git config設定pager來達到同樣的效果 為...

hibernate一些常見錯誤

1.出現該問題可能是在倆個多對多的實體類的對映配置檔案裡 錯將set的table配成了倆個實體類的表名,事實上應該設定為橋表的表名 2.出現該問題可能是在實體類的對映配置檔案裡 hibernate5.0 以後不需要建立服務註冊物件 serviceregistry 直接這樣建立 configurati...