Git簡(jiǎn)明手冊(cè)
以下都是常用的操作,并做了一些通用的規(guī)范性要求。
有些操作適應(yīng)于developer,有些適用于version manager。
準(zhǔn)備工作
配置個(gè)人本地git變量
- 配置郵箱
$ git config --global user.name eric
$ git config --global user.email eric@163.com
- 配置快捷命令
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.br branch
$ git config --global alias.hist=log
--pretty=format:'%h %ad | %s%d [%an]' --graph
--date=--date=format:'%A %Y-%m-%d %H:%M:%S'
- 配置默認(rèn)日志編輯器
# 配置為atom
$ git config --global core.editor "atom --wait"
# 也可以配置其他的,需要設(shè)置環(huán)境變量
# 提交操作時(shí),一律用一下命令,詳細(xì)填寫(xiě)comment
$ git ci
從這里開(kāi)始項(xiàng)目
Clone項(xiàng)目
$ git clone http://github.com/eric/test.git
配置本地忽略文件
# 有些本地的文件,你并不想看到它,更不想加入到版本管理,
# 建立忽略文件,git就不會(huì)顯示他們。
$ touch .gitignore
$ vi .gitignore
內(nèi)容類(lèi)似:
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
#project files #
.classpath
.project
.settings/*
.tern-project
建立本地的遠(yuǎn)程分支
$ git co --track origin/dev
$ git co --track origin/uat
$ git co --track origin/feature/groupcc
# 從此,向遠(yuǎn)程推送只需:
git push
正確的開(kāi)發(fā)姿勢(shì)
# 就是開(kāi)始之前建立分支,基于分支開(kāi)發(fā),不要直接在git倉(cāng)庫(kù)的分支上開(kāi)發(fā)。
# 基于dev,建立新需求分支
$ git co dev
$ git co -b feature/cc606
# 基于uat,建立bug修復(fù)分支
$ git co uat
$ git co -b hotfix/cc606_1
# 把本地開(kāi)發(fā)分支的程序,推送到遠(yuǎn)程倉(cāng)庫(kù),請(qǐng)管理員合并到dev或uat主分支
$ git push origin feature/cc606:feature/cc606
$ git push origin hotfix/cc606_1:hotfix/cc606_1
# 然后登陸gitlab,建立merge request
一個(gè)需求的開(kāi)發(fā),在本地產(chǎn)生了上百次commits,但倉(cāng)庫(kù)關(guān)注的是結(jié)果
# 管理員會(huì)拒絕你這些垃圾日志,只要看到最終結(jié)果
# 這時(shí)候你可以把你所有的commit合并為一次提交,這樣就不會(huì)有凌亂的日志
$ git co dev
# 重新拉取一下最新代碼
$ git pull --rebase
# 開(kāi)始合并
$ git merge --squash feature/cc606
# 這樣就會(huì)把feature/cc606的修改,在本地產(chǎn)生待提交的記錄,只要提交
$ git ci -am "req-cc606 - 增加工號(hào)必錄項(xiàng)"
# 以上merge可能產(chǎn)生conflict,另議
拉取和推送
# 拉取最新代碼
$ git pull origin
# 推送到倉(cāng)庫(kù)
$ git push origin
比較差異
# 比較不在暫存區(qū)的文件與上個(gè)版本的區(qū)別
$ git diff
# 比較在暫存區(qū)的文件與上個(gè)版本的區(qū)別
$ git diff –-cached
# 比較不在和在暫存區(qū)的文件與上個(gè)版本的區(qū)別
$ git diff head
# 比較本地分支和遠(yuǎn)程分支的差異
$ git log local_branch..origin/remote_branch
$ git diff local_branch origin/remote_branch
怎么查看某個(gè)commit的文件列表
$ git show --name-only 1fc253bd
或者
$ git diff-tree --name-only -r 1fc253bd
怎么查看某個(gè)commit下,倉(cāng)庫(kù)的所有文件
$ git ls-tree --name-only -r 1fc253bd
怎么查看某個(gè)文件的變更歷史
$ git log --pretty=oneline filename
怎么比較一個(gè)文件不同的歷史版本差異
# 先查看文件的變更歷史
$ git log --pretty=oneline filename
d34a3eb745f783bb61ed8f03a47b6c79c62d343c 代碼調(diào)整
ea08e3209ea78329696654dfe8ab79c790d9ed60 調(diào)整
6d9e65c570aae4e47fd9895e91dda0672c5261b9 修改字符集 GBK->UTF-8
78cb2ba9f163f312c51b30813335b8ad1e9ec5d4 初始化
$ git diff d34a3eb7 ea08e320 filename
如何導(dǎo)出兩個(gè)版本之間的變更文件
$ git diff 8038f96a b74cc370 --name-only | xargs tar -czvf you_tar.tar.gz
或者(windows下可能沒(méi)有zip命令)
$ git diff rv1 rv2 –name-only|xargs zip diff.zip
如何導(dǎo)出某個(gè)版本的所有文件到指定目錄
$ git archive b74cc370 | tar xC output_dic
如何導(dǎo)出某個(gè)版本的特定文件到指定目錄
$ git archive b74cc370 filename | tar xC output_dic
當(dāng)我的代碼與別人沖突,如何合并版本時(shí)以別人的版本為準(zhǔn)
# 項(xiàng)目前期版本變化較大時(shí),有時(shí)候你希望以最新的更改覆蓋,這時(shí)很實(shí)用
$ git merge --squash feature/groupcc --strategy-option=theirs
當(dāng)我的代碼與別人沖突,如何合并版本時(shí)以自己的版本為準(zhǔn)
# 兩個(gè)人做同一個(gè)方案,你的方案更優(yōu)時(shí),可以這樣做
$ git merge feature/groupcc --strategy-option=ours
或者
$ git merge feature/groupcc --s ours
如何僅合并某個(gè)分支上的某個(gè)特定的commit到當(dāng)前分支
如僅把下圖d1到d2的修改合并到m1

git co dev
git cherry-pick d2
新版本發(fā)布時(shí),你可能希望打個(gè)標(biāo)簽,以后可以隨時(shí)回顧歷史需求的提交
$ git tag -a v_cc606 -m "cc606需求 - 增加工號(hào)必錄項(xiàng)"
# 推送到遠(yuǎn)程
$ git push origin v_cc606
commit后,發(fā)現(xiàn)漏個(gè)文件,或者message寫(xiě)的不合適,修改最后一次提交
$ git add file_another
$ git ci --amend
有時(shí)候你希望根據(jù)關(guān)鍵字查找變更的歷史
$ git log --grep=keyword
有時(shí)候你希望根據(jù)committer或者author查找變更的歷史
$ git log --committer=eric
$ git log --author=eric
正在開(kāi)發(fā)一個(gè)需求,突然Bug降臨!?
經(jīng)常有這樣的事情發(fā)生,當(dāng)你正在進(jìn)行項(xiàng)目中某一部分的工作,里面的東西處于一個(gè)比較雜亂的狀態(tài),而你想轉(zhuǎn)到其他分支上進(jìn)行一些工作。問(wèn)題是,你不想提交進(jìn)行了一半的工作,否則以后你無(wú)法回到這個(gè)工作點(diǎn)。解決這個(gè)問(wèn)題的辦法就是git stash命令
# 臨時(shí)保存當(dāng)前的工作(加入當(dāng)前未完成的需求為cc606)
$ git stash save "cc606"
# 多次stash以后,列出所有的stash
$ git stash list
$ git stash list
stash@{0}: On feature/groupcc: cc606
stash@{1}: WIP on feature/groupcc: ebec8f2d Merge branch
'feature/groupcc' into 'feature/groupcc'
# 如果完成了bug修改,要繼續(xù)需求開(kāi)發(fā),取出stash內(nèi)容
$ git stash apply stash@{0}
# 以上從stash恢復(fù)應(yīng)用的行為,可能與你已經(jīng)修復(fù)的bug程序產(chǎn)生conflict,
# 你需要手工處理沖突
# 當(dāng)然以下方式可以避免恢復(fù)時(shí)產(chǎn)生沖突,但最終合并版本時(shí),你還是要處理潛在沖突
# 在指定stash上建立新分支
$ git stash branch bs stash@{0}
版本管理的約定
- 一切皆分支
- 無(wú)論需求還是bug都要基于某個(gè)基線(xiàn)分支,建立新的開(kāi)發(fā)分支
- 開(kāi)發(fā)完成后推送到gitlab,建立merge request
- 隨后可以刪除分支
- 關(guān)于編碼
- 一切程序和配置文件等用UTF-8編碼
- 提交的comment注釋也要用UTF-8編碼
-
comment標(biāo)準(zhǔn)化
- 提交comment,用git ci,詳細(xì)填寫(xiě)提交日志,不要用git ci -m
- comment的標(biāo)題要簡(jiǎn)潔、清晰,以后版本關(guān)聯(lián)和查找非常方便
-
需求按照:req-cc606:增加工號(hào)必錄項(xiàng),具體示例如下:
req-cc606:增加工號(hào)必錄項(xiàng)
--------此處空一行-------
增加手機(jī)號(hào)必錄項(xiàng),修改了查詢(xún)、維護(hù)功能。
此外,還修改了人員信息導(dǎo)出報(bào)表功能。
-
itfix按照:itfix-FN001-cc606:調(diào)整維護(hù)界面校驗(yàn),具體示例如下:
itfix-FN001-cc606:調(diào)整維護(hù)界面校驗(yàn)
--------此處空一行-------
維護(hù)界面校驗(yàn)沒(méi)有考慮空指針情況。
無(wú)法關(guān)聯(lián)到具體需求的itfix,按照:itfix-FN001:銀保跑批報(bào)空指針
格式化日志
-
有了規(guī)范的日志格式,查詢(xún)歷史就非常方便了:
$ git log --grep "分支"
-
-
bug修復(fù)流程
- 生產(chǎn)的bug,基于master分支建立修復(fù)分支
- 修復(fù)后,合并到uat、dev分支
- uat的bug,基于uat分支建立修復(fù)分支
- 修復(fù)后,合并到dev分支
- 生產(chǎn)的bug,基于master分支建立修復(fù)分支
-
關(guān)于建立幾個(gè)分支的問(wèn)題
- 生產(chǎn)、uat、集成測(cè)試分別建立分支,master、uat、dev
- master、uat、dev都要保護(hù)起來(lái),不允許開(kāi)發(fā)人員隨意提交,否則版本混亂
- 開(kāi)發(fā)人員的提交通過(guò)merge request合并到主分支
- 關(guān)于發(fā)布
- 每次發(fā)布后,建立一個(gè)tag,標(biāo)記這次發(fā)布,建議以格式release_req-cc606命名,通過(guò)tag的名字能知道發(fā)布的內(nèi)容
- 關(guān)于一個(gè)分支上的版本交叉問(wèn)題
- 無(wú)論是什么版本管理工具,按照需求的提交順序上線(xiàn)至關(guān)重要,建議宣導(dǎo)發(fā)到UAT的需求要同時(shí)上線(xiàn),沒(méi)有積壓
- 現(xiàn)實(shí)是殘酷的,一般都會(huì)有交叉,如有A、B、C三個(gè)需求在dev分支,產(chǎn)生了A、B、C三個(gè)commit,來(lái)回幾次bug修復(fù)可能commit歷史為:A、B、C、A1、C1、B1、A2、B2,這時(shí)候你可能像使用svn一樣進(jìn)行合并,需要用到cherry-pic和沖突解決相關(guān)的技巧