無論是數據科學家、算法工程師還是普通開發(fā)人員,在每個團隊協作開發(fā)任務中,Git都是必不可少的版本控制工具,因此掌握它的基本操作十分有必要。但即便是教程滿天飛的今天,開發(fā)人員在使用Git時也還是會犯一些不應該犯的錯誤。本文總結了其中的幾種常見錯誤,希望能對新手有所幫助。
force push
有時,我們會需要用force push把commit推送到遠端倉庫。
假設有2名開發(fā)人員正在合作開發(fā)一個分支
之前開發(fā)人員1已經完成更改,把代碼push到了遠程倉庫
現在,開發(fā)人員2也完成了更改,正當他準備提交時,他卻發(fā)現自己無法將代碼推送到遠程倉庫
由于開發(fā)人員2是個初學者,他Google了一下,發(fā)現了一個神奇的命令git push -f,于是進行了強制push
之后開發(fā)人員1在檢查遠程倉庫時,發(fā)現自己編寫的代碼全消失了
出現這個問題的原因是force push會覆蓋遠程倉庫中的代碼,使現有代碼全部丟失。
如果開發(fā)人員2想避免這個問題,一種理想方法是他先把開發(fā)人員1的更新從遠程倉庫pull到本地,然后把自己的代碼rebase一下,再進行push。這里我們討論的是在同一分支中從遠程到本地倉庫的rebase。
git push -f這個命令非常不安全,除非有絕對的必要,大家最好還是不要用它。它會把本地分支的提交覆蓋遠程推送分支的提交,給協作的同伴帶去不少麻煩,即便是上面的解決方案,它也可能存在一個時間差的問題,因為你不可能時刻掌握同伴的工作進展。
所以如果大家都用正確的git工作流,讓每個開發(fā)人員都擁有自己的功能分支,這種情況根本不會發(fā)生。
Rebase
如果你想把一個分支的修改合并到當前分支,你可以用git rebase。它和git merge的區(qū)別是merge有一個合并commit的步驟,而rebase是把所有commit都串聯在一起,讓你本地的分支歷史看起來像沒有經過任何合并一樣。
假設有2名開發(fā)人員正在合作開發(fā)一個功能分支
開發(fā)人員1率先完成了一系列commit,并將其推送到遠程功能分支
之后,開發(fā)人員2把遠程功能分支的最新更改pull到本地
開發(fā)人員2向本地功能分支添加了一堆commit
這時,他想把本地倉庫的更新重新rebase到遠程倉庫中,于是他把整個預發(fā)分支(release branch)在本地功能分支上rebase了一下。這里我們討論的是在不同分支中從遠程到本地倉庫的rebase
現在,開發(fā)人員2試著把代碼push到遠程功能分支上,由于提交歷史記錄已更改,這個操作不被允許,他只能又開始用git push -f
最后,當開發(fā)人員1想從遠程倉庫提取最新代碼時,由于提交記錄已更改,他被迫需要處理大量代碼沖突問題
常規(guī)rebase
開發(fā)人員2的操作
如上圖所示,rebase遠程倉庫會改變提交歷史記錄,并在其他開發(fā)人員嘗試從遠程倉庫中提取最新代碼時產生問題。處理這種情況的理想方法是始終只rebase本地倉庫,本地倉庫中的任何commit都不應該被push到遠程倉庫。
如果別人事先已經把commit推送到遠程功能分支,那么你最好先用pull命令把更新拉到本地,用merge和你的修改合并,因為merge不會改變提交歷史,而rebase會。
此外,和上個問題一樣,如果使用正確的git工作流,每個開發(fā)人員都會有自己的功能分支,這時,開發(fā)者在自己的功能分支上進行更新并且在遠程功能分支上做rebase是不會報錯的,因為沒有其他開發(fā)人員從同一個遠程功能分支中提取代碼。無論如何,盡量避免重新定義遠程倉庫。
Rebase是一個非常強大的功能,使用時也需謹慎。
amend
git amend命令的作用是修復最近一次commit,讓你合并你緩存區(qū)的修改和上一次commit,而不是提交一個新的快照。這里需要注意一點,它不是修改最近一次commit,而是整個替換掉原commit,所以對Git來說這是一個新的commit。此外,它還可以用來編輯上一次的commit描述。
假設有2名開發(fā)人員正在合作開發(fā)一個功能分支
開發(fā)人員1率先完成了commit,并將其推送到遠程功能分支,我們把它稱為“old commit”
之后,開發(fā)人員2把最新代碼從遠程功能分支pull到本地功能分支
然后他開始處理本地倉庫中的代碼,在這個過程中,他沒有向遠程倉庫push任何commit
這時開發(fā)人員1突然發(fā)現之前的commit中存在bug,他用amend命令修復了本地倉庫里的最近一次commit,我們把它稱為“new commit”
開發(fā)人員1嘗試把這個新commit重新push到遠程功能分支,由于提交歷史記錄發(fā)生了變化,這個操作報錯了,于是他調用了git push -f
現在,當開發(fā)人員2想從遠程功能分支中提取最新代碼時,git會注意到提交歷史記錄的變化并創(chuàng)建合并的commit。因此當他pull到本地后,他會在本地倉庫里發(fā)現“commit old”和“commit new”,這就破壞了amend這個操作的意義。
最后,即便開發(fā)人員2從遠程分支到本地分支執(zhí)行rebase,這個“commit old”還是會出現在本地倉庫中,它仍然會作為歷史提交的一部分。
amend commit會更改提交歷史記錄,所以當其他開發(fā)人員嘗試從遠程倉庫提取最新代碼時,修改遠程倉庫中的commit會產生混淆。
為了避免這個錯誤,最好的方法是只在本地倉庫里修改commit,不要對遠程庫里的commit做任何修改。當然,一人一個分支也不會出現這個問題。
Hard reset
git reset命令是用來將當前branch重置到另外一個commit的。它不會產生commit,而是只更新一個branch(branch本身就是一個指向一個commit的指針)指向另外一個commit。
Hard reset的命令是git reset --hard
此外,git reset還有--soft和--mixed,只不過它們都沒有Hard reset那么不安全
假設開發(fā)人員1正在開發(fā)一個功能分支,并在本地倉庫中完成了5次commit
與此同時,他還正在處理尚未提交的兩個文件
這時,如果他運行了git reset --hard
那么功能分支中的最新commit會變成是commit4,commit5丟失
同時他正在處理的那兩個未提交文件也會丟失
這時commit5還在git內部,只不過對它的引用丟失了,我們可以用git reflog把它恢復,但總體來說,hard reset還是很不安全。在git中使用reset命令時要非常小心,如果必須得用,確保你已經完全評估所有情況。
小結
綜上所述,為了避免使用git時出錯,我們可以牢記這幾條教訓:
避免多人在同一分支上協作。上述四個例子中有三個都是在說明這個問題,在日常工作中,遵守正確的工作流非常重要,要確保只有一個人在一個功能分支上工作,這是技術主管、高級開發(fā)人員尤其需要注意的。
不要到處實用force push。
如果萬不得已必須使用force push,先評估其他方案,把它作為最后的手段。
不要試圖修改遠程倉庫里的commit,要只在本地倉庫中更改commit歷史記錄。但即便是在本地倉庫里,用rebase還是要謹慎。
-
代碼
+關注
關注
30文章
4790瀏覽量
68650 -
Git
+關注
關注
0文章
200瀏覽量
15776
原文標題:實用:Git中的一些常見錯誤
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論