GIT版本管理:場景命令實戰

#0 系列目錄#git

Git 相比 Subversion,不管概念上仍是使用上,複雜度實際上是高出一個等級的。爲何這麼說?分別看下 git help -a 和 svn help 命令清單的對比,單按這個來看,就若是要掌握全部命令的用法,Git 的學習曲線絕對是比 Subversion 高的。儘管如此,但仍是有愈來愈多項目開始用 Git 來作源碼管理了。程序員

實際中,咱們用到的的 Git 命令仍是頗有限的,可能也就 git help 中那些而已。github

#1 「新人報道」# 你剛入職一家公司,或新加入某個團隊,立馬參與到一個項目中,那麼就得獲取項目代碼,開始你的項目生涯。這個時候通常你須要克隆一份項目代碼,下面都以 GitHub 上的項目地址爲例:sql

$ git clone git@github.com:akun/pm.git

以後就進入項目目錄,運行項目中的構建腳本,而後就能夠熟悉代碼,展開具體工做了。編程

固然,有的時候,有一個新項目是由你發起的,你要將初始化的項目工程放到 Git 版本倉庫中vim

$ mkdir pm
$ cd pm
$ git init
$ touch README.md
$ git add README.md
$ git commit

Git是分佈式的版本控制系統,因此剛纔的操做,算是已經在你本地版本控制起來了,爲了推送本地倉庫到遠程倉庫,就還得執行:分佈式

$ git remote add origin git@github.com:akun/pm.git
$ git push -u origin master

通常這個時候都會設置下 ~/.gitconfig 或 .git/config 中的配置,最基本的就是用戶名和郵箱。svn

確認當前的 Git 配置信息:工具

$ git config --list

設置用戶名和郵箱:佈局

$ git config user.name akun
$ git config user.email admin@example.com

剛纔的命令只是對 .git/config 生效,若是想全局生效,也就是 ~/.gitconfig,就得加上 --global 參數,好比:

$ git config --global user.name akun
$ git config --global user.email admin@example.com

#2 平常工做# 當你已經逐漸融入了一個項目,可能一天的工做場景或完成某個任務的工做週期是這樣的:

##2.1 更新## 不管是清早或下午或晚上,開始了你的一天工做,你首先會更新你的工做目錄:

$ cd ~/projects/pm
$ git checkout develop  # 我想在 develop 分支上開始一天的工做

更新方式一:

$ git fetch --all  # 從遠程倉庫獲取全部分支的代碼變動
$ git merge

更新方式二:

$ git fetch --all
$ git rebase  # 默認就衍合 develop 分支的代碼了

更新方式三,能夠認爲是 fetch 和 merge 的合集:

$ git pull  # 懶得理解 fetch 和 merge 就直接 pull 吧

這樣你就能夠在最新的項目代碼基礎上工做了。

註解:

  • git pull --rebase 至關因而前面的方式二的合集

  • 這裏說的三種方式,可能每一個人或團隊都有本身的習慣吧

  • 想了解 Git 中的「衍合」,能夠實踐下這個文檔:Git-分支-分支的衍合

##2.2 修改## 可能你寫了一個新的模塊,須要歸入項目的版本控制:

$ git add tools.py

可能你發現某個模塊已經陳舊了,再也不使用了:

$ git rm utils.py

可能你發現一個模塊的命名不太合理,須要更名:

$ git mv model.py models.py

可能你要建立一個新的較大的模塊,須要歸檔爲目錄的方式:

$ mkdir groups
$ touch groups/__init__.py
$ git add groups/__init__.py

註解:

Git 不支持空文件加加入版本控制,非得必要咋辦,後續的其它場景會簡單說明下。

可能你發現要寫的模塊代碼佈局相似於舊的模塊,直接複製個代碼模版:

$ cp users/tests.py groups/tests.py
$ git add groups/tests.py

註解:

Git 沒有自帶的所謂 cp 命令

##2.3 檢查## 忙碌的一天過去了,或者一個任務完成了,這個時候通常會將你的工做成果,也就是代碼更新到版本倉庫(分爲本地版本倉庫和遠程版本倉庫)。

習慣上會先檢查下修改狀態:

$ git status

看到一些 Git 狀態信息,確認是修改了哪些文件,以後通常會本身 code review 一下代碼的改動,可能有的人會習慣直接用 Git 方式來查看:

$ git diff

這裏的 diff 只是查看其中「工做目錄」和「暫存區域」的區別。要查看「暫存區域」和「本地倉庫」的區別,能夠用:

$ git diff --staged  # 或 git diff --cached

註解:

最好理解下三個區的概念,以代碼角度來理解:

工做目錄:git clone 後得到的一份本地的代碼,也包括新編輯的,還沒有加入版本控制的代碼

暫存區域:git add 後暫存起來,還沒有 git commit 的代碼

本地倉庫:git commit 後正式被版本控制記錄起來的代碼

能夠看下圖,能更好的理解這三個區:

輸入圖片說明

而後本地運行下相關的單元測試,確認是否有問題。通常來講這個時候,沒有什麼特殊狀況,就直接進入「提交」甚至是「推送」階段了,而後結束一個工做日或工做週期,但不免會有些特殊狀況出現。

##2.4 取消修改## 當你 code review 完後,發現有些改動不滿意;或者運行完單元測試,發現有些測試用例沒經過,你可能會進行取消這些修改的操做。

若是還沒 add,那麼能夠:

$ git checkout -- main.py

爲了不恰好跟分支名重合,因此加了兩個斜槓(雖然機率很低),若是已經 add 了,但還沒 commit,那麼能夠:

$ git reset HEAD main.py

萬一剛提交完畢,也就是已經 commit 了,才發現代碼有問題,好比:忘記把某個文件提交了,這個時候咋辦?Git 好處是能夠覆蓋上一次提交,那麼能夠:

$ git add tests.py
$ git commit --amend

上面還只是簡單的撤銷操做,Git 還能支持更高級的重寫歷史功能,想掌握高級技能的能夠實踐下這個文檔:Git-工具-重寫歷史

##2.5 解決衝突## 有時候同別人合做寫一個模塊的代碼,會把對方代碼合併或衍合過來,好比:對方修復了某個缺陷,你恰好也須要這個修復;再好比:對方完成了某個特性,你也恰好須要用下這 個特性等等各類狀況。

大多數狀況,代碼的合併或衍合不會衝突,但也有衝突的狀況,分兩種狀況說明,第一種是合併操做時候有衝突

$ git fetch --all
$ git merge bugfix/remove_error
# 這個時候就提示你代碼衝突了,處理完衝突的代碼後
$ git diff  # code review 下代碼
$ git add remove.py
$ git commit
# 日誌中就多了一條合併操做的日誌了

另外一種是衍合操做時有衝突

$ git fetch --all
$ git rebase bugfix/remove_error
# 這個時候就提示你代碼衝突了,處理完衝突的代碼後
$ git diff  # code review 下代碼
$ git rebase --continue  # 有時候會 git rebase --skip
# 直到不用再 rebase 爲止

##2.6 提交到本地版本倉庫## 最後,一切確認沒問題了:code review 完畢,本身以爲代碼滿意了;有可能也合併完別人的修改而且沒有衝突了;運行單元測試也經過了。那麼就提交代碼吧:

$ git commit

##2.7 推送到遠程版本倉庫## Git 中的 commit 只是提交到本身本地的版本控制倉庫,若是想分享你的代碼提交,還須要推送到遠程的版本控制倉庫:

$ git push

#3 在分支工做# ##3.1 建立新的本地分支## 肯定要新開個分支來寫代碼,這裏以貢獻新特性爲例子:

$ git checkout -b features/batch_remove
$ git branch -a  # 確認已經在新分支中工做了
$ git log  # 能夠確認是基於剛纔的分支新分出來的

這裏已經隱含了自動切換到新分支的動做了。

##3.2 在新的本地分支工做## 相似,「平常工做」中的工做週期操做,這個時候,你就能夠在新分支中進行大刀闊斧的工做了,直到分支中代碼符合要求。

##3.3 推送成爲做爲遠程分支## 若是想把分支分享給別人,能夠推送到遠程版本庫,這樣別人能夠根據須要來把你的分支代碼更新到他本身的本地倉庫,例如:

$ git push origin features/batch_remove

##3.4 合併或衍合遠程分支## 在分支中工做一段時間後,確認相關的功能代碼、測試代碼、文檔等都提交完畢了,單元測試經過,你們 code review 一致認爲沒問題,審覈經過,最後該分支的持續集成(CI)完整 build 經過。這個時候,就能夠進行合併的操做了。

其實前面也提過相似操做,這裏再相似重複一遍,若是用合併:

$ git fetch --all
$ git merge features/batch_remove
# 若是沒提示衝突,那就合併成功
# 若是這個時候就提示你代碼衝突了,處理完衝突的代碼後
$ git diff  # code review 下代碼
$ git add batch.py
$ git commit
# 日誌中就多了一條合併操做的日誌了

若是用衍合:

$ git fetch --all
$ git rebase features/batch_remove
# 若是沒提示衝突,那就衍合成功
# 若是這個時候就提示你代碼衝突了,處理完衝突的代碼後
$ git diff  # code review 下代碼
$ git rebase --continue  # 有時候會 git rebase --skip
# 直到不用再 rebase 爲止

這裏也提下直接合並本地分支,有時候你建立的分支只是本身用用,沒有共享給別人,由於本地已經有了這份分支代碼了,那麼就省去 git fetch 操做,相似上述方式合併或衍合代碼就行。

對比 Subversion 的分支合併操做,實在是簡化很多。

##3.5 刪除分支## 若是確認工做完畢的分支再也不須要了,那就記得及時清理掉,刪除遠程分支

$ git push origin :features/batch_remove

刪除本地分支:

$ git branch -d features/batch_remove

順便說下,一段時間後,必定有一堆別人的分支,而後你 git fetch 下來了,這樣就出如今本地的分支清單中,但遠程版本庫中已經刪除了,若是想本地分支清單幹淨些,能夠在 git fetch 時候這樣執行:

$ git fetch --all -p

#4 發佈分支# 可能在平時的研發分支工做一段時間後,而且測試完畢,你們以爲符合發佈條件了。終於能夠進入到版本發佈階段的工做了。

##4.1 建立發佈分支## 通常來講這個時候已經將在某個發佈分支上工做了,好比:

$ git checkout -b release-1.2 develop  # develop 就是平時的研發分支
$ release.sh 1.2  # 好比有個執行發佈腳本
$ git commit

##4.2 打標籤## 肯定能夠發佈了,就開始打標籤吧,好比:

$ git checkout master
$ git merge --no-ff release-1.2
$ git tag -a v1.2
$ git tag  # 確認下打上了標籤了
$ git push origin v1.2  # 推送標籤到遠程版本庫

#5 其它場景# code review 查看代碼,要知道對應代碼是由誰寫的,好詢問了解具體代碼的思路:

$ git blame

跟蹤問題時候,會查看日誌,更方便歷史代碼定位:

$ git log

以爲完整的 Git 命令太長,想用相似 Subversion 的縮寫命令,能夠用 alias,好比配置文件中能夠寫上:

[alias]
    br = branch
    ci = commit
    co = checkout
    diffs = diff --staged
    st = status
    lg = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n''%C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all

有時候合併或衍合代碼,但本地有修改了一半的代碼沒有提交,能夠先暫存起來:

$ git stash
# 合併或衍合完畢代碼後
$ git stash pop  # 恢復剛纔修改了一半的代碼

原來的一個項目想拆分多個項目,又想保留版本倉庫記錄,能夠用下 git subtree split,例如:

$ git subtree split --prefix=plugins/sqli

Git 不支持空文件夾加入版本控制,變通方式:

$ mkdir downloads
$ vim downloads/.gitignore  # 增長 * 和 !.gitignore 這兩條規則

對於習慣命令行下編程的程序員來講,多看幫助老是好的,直接執行:

$ git help

能夠看到 Git 的經常使用命令,若是想看到更全的 Git 命令,能夠執行:

$ git help -a

單獨查看某個命令的幫助,能夠執行:

$ git help add  # 好比 add 命令

這裏順帶說下幾個使用 Git 的好習慣,但有的其實跟 Git 聯繫也不算大,只是順帶提下:

**保持工做目錄乾淨。**或者說工做目錄中的代碼變動就爲了完成一個任務,即一次只作一件事。完成任務後,就直接 git commit 提交到本地版本倉庫的某個分支中,而不用擔憂其它任務做出的代碼變動無提交。而且,對於分支切換更方便,而不用擔憂代碼被覆蓋或衝突的問題。

**Git 的日誌信息足夠有效。**足夠有效的意思,是說此次提交做出的變動摘要,只要別人閱讀了日誌就能知道大概,若是爲了深刻了解變動細節纔會去查看具體代碼變動。

**git commit 前 code review。**code review 自己就是個好習慣,提交前確認是一種更爲嚴謹的方式,若是以爲本身 code review 發現不了什麼問題,那麼隨便從身邊抓個會代碼的,跟別人講解下代碼變動的內容,說不定會發現你沒考慮到的問題。

**git commit 前跑單元測試。**寫單元測試自己也是個不錯的習慣,若是項目自己已經有了完備的單元測試覆蓋了,那麼你對代碼的修改,應該能經過單元測試,因此提交前執行一遍是否經過。若是沒經過,就得看下是功能代碼寫的有問題,仍是測試代碼有問題,好比:功能需求或接口設計有變化,而測試代碼沒有同步更新。

**有代碼變動及時提交。**有 Git 這種版本控制工具,自己就是爲了記錄研發過程,避免意外致使代碼丟失,若是爲了完成某個任務須要很長時間,代碼也好久沒有提交,風險過高。這個時候,通常會本身開個分支,而將代碼提交到分支中,既解決代碼要及時提交的問題,又解決代碼提交頻繁,可能形成代碼不穩定影響別人的問題,由於那個分支只有你本身在工做。而這一點,Git 分支的功能更爲強大,更加鼓勵多開分支。

相關文章
相關標籤/搜索