Git使用對於我們來說是熟悉不過的了,但總有一些技術,即便我們日日相見,但離清清楚楚總有很遠的距離,更可怕的是,這個距離似乎並沒有縮短的趨勢。

那麼,我是要寫些能夠讓git變得清清楚楚的東西么?額,並不是,要弄清楚,還是得花時間去看官方文檔,去看原理,以上只是提醒一下大家。

其實,對於我個人而言,我是沒有系統學習過git的(當然這是十分不可取的),當時是在使用SVN,後來公司切成了Git,然後看了幾個命令就直接開始使用了,相信這也是很多人的開端。初初使用時,總不自覺去與SVN做對標,但是,其實對的很艱難,幸而我忘性比較大,沒幾天就忘了SVN命令了,才使得Git的使用更加順暢。

Git的一些優質特性,總結起來就是完全分散式、快速、低成本分支等等,不再贅述,現在它在我眼中就是版本管理工具應有的樣子(畢竟我已經忘了SVN)。

本文僅僅記錄了一些我在Git使用過程中的一些實戰經驗,各個命令有寫詳細的注釋,可以關注一下,整體內容不系統,但會持續更新。

冷啟動

剛剛提到,我是"被迫"使用Git的,就不得不提一下,我的Git冷啟動。記得我第一次使用的時候看同事寫了一個類似下面的一些命令的wiki,雖然很久以後才明白這些命令都是個啥,但絲毫沒影響我用的飛起,且很長時間都沒需要查其他命令。

# 這是一套比較常用的開始一個新項目的git命令集

# 克隆遠程倉庫到本地
git clone http://gitlab.sftcwl.com/fe/knight.git

# 在使用gitlab時,我們一般是在gitlab頁面上直接新增遠程分支,這時需要在本地建立遠程分支的跟蹤分支【1.6.2以上版本】;
git checkout --track origin/develop

# 此時自動切到分支develop上,just coding

# 將所有文件納入版本控制,多數使用是都直接"add .";
git add .

# 提交,附帶注釋
git commit -m "some commit info"

# 與遠程倉庫交互
# 完整的命令是 git push [遠程名] [本地分支名]:[遠程分支名],但是由於我們建立的是跟蹤分支,可以直接推送;同時注意,如果遠程分支不存在,此命令會自動創建同名遠程分支;
git push

# 與遠程倉庫交互
# 將遠端數據拉到本地倉庫,並不自動合併到當前工作分支
git fetch

# 與遠程倉庫交互
# git pull 可以理解為使用給定的參數運行 git fetch 命令,並調用 git merge 進行合併;
# 同 git push 一樣,這也是建立跟蹤分支後的簡寫;
git pull

這套命令下來非常簡單,理論上,只要你一直一個人開發一個項目,這一套命令就足足的了;但現實中,多數情況下是很多個人在一個項目上一起造,這也正是版本管理更直接的意義;

下面是我在開發中遇到的一些情況,希望對大家有所幫助;

刪除文件

對於前端來說,node_modules是用來存放第三方代碼的,一般並不納入版本管理,但是在首次提交時,有時會忘記在.gitignore中添加忽略,導致node_modules被上傳到git倉庫,此時怎樣處理比較方便、恰當呢?

# rm是與add相對應的命令,加cached參數的意思是將node_modules從版本控制中移除,但並非真正在硬碟上刪除node_modules,-r的意義就顯而易見了;
git rm --cached node_modules -r

# 在.gitignore文件中將node_modules加入忽略;

# 常規提交代碼;
git add .
git commit -m "add node_modules in ignore file"
git push

合併

無論是在開發分支上需要時不時同步master分支代碼,還是上線前需要將開發分支代碼合入到master,我們都需要經常使用合併命令。

# 奇怪的是,這個命令運行完,每次的提示可能都不一樣,這是為什麼呢?
git merge branch-name

在運行git merge命令時,有時會出現『Fast forward』的提示,這是由於當前分支所在的提交對象是要併入的分支的直接上游,Git此時只需要把分支指針直接移至下游,所以這種合併過程可以稱為快進(Fast forward),最幸福的merge;

當merge的兩個分支,並非簡單的上下游關係,Git會使用兩個分支的共同祖先,及兩個分支各自末端的提交對象,進行一個三方合併計算,並自動創建一個新的提交對象;此時是有可能會出現衝突,需要人手動合併的。

# 合併遇到衝突了,git也沒有簡單的放棄,而是給你匯總出一個結果,方便你去抉擇
# 手動將代碼修正到你滿意的狀態後,需要將它們標記為已解決狀態
git add filename

# 在提交記錄中,標明此次提交為解決衝突
git commit

讓你的commit可以被命名

我有一個不好的開發習慣,每次開發時,想起提交來就提交,每次提交的內容非常散亂,沒辦法概括,經常改好幾個bug才想起來提交一次,或者一個bug改到一半提交一下。這當然是很不專業的了,這大概是將git當做一個代碼管理工具,而非版本管理了;

讓你的commit可以被命名,簡單來說就是一次提交只做一件事,而且是一件完整的事情,但是說起來容易,實施時經常是,我以為OK了,提交了,結果發現漏了一些東西,這時要怎麼辦呢?

git commit -m "add function user management"
git add forgotten_files

# 使用--amend選項,相當於將兩次提交合併為同一條,同時此命令還可用於修改提交說明
git commit --amend

可能不能挽回的操作

任何已經提交到Git的數據都可以恢復,即便在已經刪除的分支中的提交。但是,這不意味著任何時候你的數據都能夠恢復,對於那些沒有提交過的數據,Git是無能為力的。

有時存在這樣一種場景,當你修改了某個文件,比如說readme文件,並且已經暫存,這時候你覺得這個修改是沒必要的,怎麼辦?

# 一步一步來,首先得撤銷暫存;
# 前面有提到過,可以使用rm命令將對文件的跟蹤取消掉,但一定要記得加cached參數
git rm --cached readme
# 其實rm命令還是用起來很危險的,更提倡的是使用下面的命令將指定文件變更到unstage狀態
git reset HEAD readme

# 下一步將文件代碼恢復到修改之前
git checkout -- readme

# 運行完畢,文件回到了修改前,且無法挽回;

分支管理

對於分支的管理,有很多完備的方案,但是我這裡想說的並不是一個完備的方案,而是一個在開發中形成的簡化方案。

這個方案僅針對中小型項目,10人以內的合作項目。很多分支管理方案,主張維護多個長期分支,其實對於中小型項目是沒有必要的,反而由於穩定分支多、流程長,可能導致一些流程上的失誤。

我們的方案是,僅僅維護一個長期分支,也就是master分支,所有分支都是從master檢出的特性分支,分支命名採用「版本_特性_開發人員代號」的方式,同一個版本的多個分支,在集成測試前合併至同一分支即可,所有分支合完即刪(本地分支、遠程分支均需刪除);在分支命名中加入開發人員代號,也可以使分支的歸屬更清晰明確,給開發人員一種暗示,敦促其完成分支的合併,並及時檢視是否有多餘的、未完成的分支。

但是很快會有同學說,那如果開發時有一些公共的組件之類的代碼怎麼辦呢?我們的方案也非常簡單,單拉分支,完成公共特性開發,並提merge request給項目的owner,由owner(只有owner有master分支的提交許可權) review代碼後,直接合入master。這裡不得不提醒大家,這樣可能會造成生產環境代碼與master代碼不一致,但是如果上線打過tag,也沒必要擔心;

這一套下來,能夠滿足99%的開發場景,而我們也實在沒有必要為1%的可能性,增加我們分支管理的複雜度。

# 上面提到分支的刪除,本地分支的刪除非常簡單;
git branch -d local_branch_name

# 對於遠程分支的刪除,我們使用什麼命令? git push [遠程名] :[遠程分支名]
# 這個命令真是有點無厘頭,據說來源於git push [遠程名] [本地分支]:[遠程分支],可以理解為把空白推送到遠程分支,遠程分支就被刪除了
git push origin :remote_branch_name

Git Status

搞事情前習慣敲一下 git status 命令,來看一下情況,或者在使用的代碼編輯器上引入Git相關的插件,時刻注意自己所在的分支,修改的狀態等等;

當你反覆被拒絕時

當你各種姿勢都提交不了代碼,各種方式都合併不了分支,當你反覆被拒絕時,仔細閱讀它給出的理由,大多數時候它都不是在敷衍你。


推薦閱讀:
相关文章