git 教程 : git 是如此的好用 branch

Git 使用

官方文檔: https://git-scm.com/doc

推薦看看這本介紹 Git 的電子書,看完什麼都知道了,介紹的很詳細
Git電子書下載 【PDF】 【EPUB】 【MOBI】javascript

我理解的 Git 是個什麼東西

Git是如今流行的 VCS(「Centralized Version Control Systems」 版本控制系統)之一。版本控制系統主要目的是,控制項目不一樣版本,可隨時回溯到任何須要的版本。
如軟件開發行業,版本控制系統扮演着不可或缺的重要角色。
VCS能夠把軟件開發的各個崗位鏈接起來,各自完成本身的工做,且層次分明,前端和後臺的工做同時進行。 VCS能夠把全部管理的文件都進行版本標記,若是任何文件修改出錯,均可以隨時恢復到前面的任何版本。
說白了, VCS能夠把開發人員緊密聯合起來,你們同時進行開發,不會出現先後端融合錯誤。

使用 git 每一個用戶都會在本地擁有 git 倉庫的全部信息,過往記錄,因此能夠隨時隨地的提交代碼。html

git 對文件版本的記錄區別於其它 vcs, 其它vcs是對每一個版本的文件進行標記,而 git 是對每一個版本的全部文件進行快照,並根據項目內的全部文件計算出 hash 值來記錄版本號。保證完整性。前端

git 最讓人癡迷的就是分支了 (branch)

來欣賞一下 Bootstrap 的部分提交記錄和目前的分支狀況java

clipboard.png

clipboard.png

三種狀態

你的文件可能處於尺寸三種狀態之一:已提交(committed)、已修改(modified)和已暫存(staged)
由此引入 Git 項目的三個工做區域的概念:Git 倉庫、工做目錄以、暫存區域。git

基本的 Git 工做流程以下:github

  1. 在工做目錄中修改文件。
  2. 暫存文件,將文件的快照放入暫存區域。
  3. 提交更新,找到暫存區域的文件,將快照永久性存儲到 Git 倉庫目錄。

安裝

windows 的我就不說了,須要的請自行百度。
Mac 系統在安裝 Xcode 的時候就會自動安裝
查看當前版本正則表達式

git --version
# git version 2.17.2 (Apple Git-113)

初次配置

git 自帶 git config 工具來修改 git 的配置文件shell

  1. /etc/gitconfig 系統上每個用戶及他們倉庫的通用配置,帶 --system 參數使用 git config 時,會讀寫這個文件
  2. ~/.gitconfig 是隻針對當前用戶。 帶 --global 參數可讀寫此文件
  3. 當前目錄是正在使用的倉庫時,配置文件路徑是 .git/config

每個級別覆蓋上一級別的配置,因此 .git/config 的配置變量會覆蓋 /etc/gitconfig 中的配置變量。vim

用戶信息

安裝完git,第一件事就是設置用戶名和郵件地址,這些信息會在每次提交時使用windows

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

指定git默認的文本編輯器

默認的編輯器是 vim,若是你想自定義編輯器,能夠經過這個指令指定:

$ git config --global core.editor 編輯器名稱

查看配置信息

git config --list 能夠查看你的 git 配置信息

$ git config --list
user.name=John Doe
user.email=johndoe@example.com
...

初始化 Git 倉庫

在當前目錄下初始化倉庫

git init

這個命令會將本目錄初始化爲一個代碼倉庫,並在目錄中增長 .git 目錄,裏面是關於本倉庫的全部信息。
初始化以後,目錄中的文件並無加入到 git 的版本控制中,須要手動將文件添加到 git 的控制列表中,操做見下一步。

$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version

Git 本地庫的常規操做

忽略特定文件

在 git 管理的目錄下 新建文件 .gitignore
如:

*.[oa]
*~

上面的文件意思是忽略全部以 .o .a 的文件,忽略以 ~ 結尾的文件

.gitignore 的格式規範:

  • 空行 或 # 開頭的行會被忽略
  • 可使用標準的 glob 模式匹配
  • / 開頭防止遞歸
  • / 結尾指定目錄
  • ! 反向選擇

glob shell 所使用的簡化了的正則表達式

  • * 0個或任意個字符
  • [abc] 任意其中一個字符
  • ? 匹配一個字符
  • [0-9] 表示匹配任意中間的字符
  • ** 兩個星表示任意中間目錄 a/**/c a/b/c a/d/c

查看當前狀態

git status

查看當前目錄下的文件狀態,若是有文件未加入到跟蹤中,會提示你。

git status -s

能夠查看簡短的報告

git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

?? 表示未跟蹤的文件
A 表示新添加的文件
MM 右邊的M表示修改後未保存到暫存區,左邊表示修改並放入了暫存區

添加文件

若是咱們新建了一個名爲 README 的文件,git status 會顯示文件沒有被跟蹤,經過如下指令把文件添加到 git 的文件跟蹤中。
加入到跟蹤中後,沒有 commit 以前,文件處於暫存區。

git add README

若是這時候修改了 README 文件,再用 git status 查看狀態的時候,會看到提示 changes not staged for commit,此時若是想在下次 commit 的時候提交此次修改,須要再次 git add 這個文件。
git add 能夠理解爲標記文件到下次提交,而非只是添加文件到跟蹤狀態

查看區別

在修改了文件以後,沒有添加到暫存區以前,能夠用 git diff 查看先後版本的區別

這是在文件沒有添加到暫存區的時候的查看方式,在存入後,須要用 git diff --cached 來查看不一樣

提交文件

git commit

這會打開默認的文本編輯器,讓你輸入這次提交的信息。就像平時用 vi 編輯文本那樣,按 i 進入輸入模式,而後輸入你要寫的話,再 esc wq 保存退出就會提交了。

或者用簡短的方式,直接在命令中輸入這次提交的信息,多個 -m 參數會做爲多個分段。

git commit -m '初次提交'

若是閒每次添加文件麻煩,能夠用 -a 參數跳過添加到暫存區的操做,直接在提交的時候把全部已經跟蹤的文件上傳。

git commit -a

移除文件

移除文件並取消該文件的跟蹤,須要用 git rm 指令,並刪除本地文件。
若是隻是在目錄中刪除了文件,在 git status 的時候會提示文件沒有添加到跟蹤中。

若是文件已經添加到暫存區,且修改了文件尚未提交,此時刪除文件就須要用 -f 參數了。

只移除文件跟蹤,不刪除文件

git rm -cached README

git rm 後面還能夠跟 glob 模式的匹配字符串

移動文件

git mv 給文件重命名用這個指令
其實它是三個指令的集合

mv README.mb README
git rm README.mb
git add README

因此用 git mv 會更方便一些。

查看歷史

git log -p -2

-p 顯示不一樣版本的區別
-2 顯示最近的再次更新

--stat 能夠查看每次更新的簡略信息
--graph 以字符圖的樣子顯示分支狀況

clipboard.png

clipboard.png

撤消操做

有時候,在提交了以後發現有幾個文件沒有提交,能夠用 git commit --amend

git commit -m "initial commit"
git add forgotten_file
git commit --amend

若是在你提交以後,在沒有修改文件以前立刻添加未提交的文件,再 --amend 就會打開上次提交的註釋,接着編輯信息,而後再提交。

Github 遠程代碼倉庫的使用

查看當前目錄下的遠程倉庫 URL

git remote
git remote -v
$ git remote -v
diary    git@github.com:KyleBing/Diary.git (fetch)
diary    git@github.com:KyleBing/Diary.git (push)

在URL前面若是顯示 origin 那是 git 給 URL 倉庫的默認名字,

添加遠程倉庫

git remote add tb git@github.com:KyleBing/TouchbarBBT.git

這樣就添加了 git@github.com:KyleBing/TouchbarBBT.git 的倉庫,別名爲 tb

這時候拉取遠程倉庫內容的時候,直接用 tb 代替 git@github.com:KyleBing/TouchbarBBT.git

從遠程倉庫拉取內容

git fetch [倉庫別名]

這個指令會拉取遠程倉庫的全部內容,包括全部分支。

git pull

會拉取遠程分支到當前分支,並自動合併。

推送到遠程倉庫

git push [倉庫別名] [分支名]

會將你的項目推送到遠程

查看遠程倉庫

git remote show [倉庫別名]

在沒有設置倉庫別名的時候,git 會默認把這個倉庫命名爲 origin

$ git remote show tb
* remote tb
  Fetch URL: git@github.com:KyleBing/TouchbarBBT.git
  Push  URL: git@github.com:KyleBing/TouchbarBBT.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local ref configured for 'git push':
    master pushes to master (local out of date)

給遠程倉庫重命名

git remote rename origin tb

重命名 origintb

git remote rm tb

移除遠程倉庫 tb

定義發佈版本 tag

查看標籤

git tag

列出已有標籤

git tag -l 'v1.8.5'

只查看 v1.8.5 的相關版本

v1.8.5
v1.8.5-rc
...

建立 annotated 標籤

添加 annotated 標籤,用 -a 參數

git tag -a v1.4 -m "tag version info"
git show v1.4

能夠查看標籤和對應的提交信息

建立 light-weight 標籤

git tag -v1.4 -lw

不須要填寫提交信息

後期打標籤

查看過往提交記錄,而後取一個記錄的校驗和的部分字符串,把該提交打成標籤

git log --pretty=online

# 顯示爲
86bc9a426f04817fe47c07685ac60e0fcdd33af9 (HEAD -> master, tb/master) 添加外部連接
4200265a6990c78fb5d0667eb0bbb99ab2760fc0  Merge branch 'master' of github.com:KyleBing/TouchbarBBT
6df11cb1ee1726291d8ef20da1a93773a8e40fff Last
6529785f35f5f2fd6333d95430d46e6dc75c590f Update README.md
aa6a05ba99933e5505969d36f66191a499e7c2b8 文章發佈前的版本
7eaa5924d0b5e7675d90d9b31b8daedaacaca0ea 定稿
4f2320c2dcbe5ccd9dac551817cbc90653fd377b 調整按鈕尺寸大小,正在播放背景色改成黑色
18dce9bf2c84183e9030d5f7e8431ca2c0504a57 Update README.md
af58e9c024ecbe2994d0c3bb21ab112dbed008fa 更新說明文檔
04da2e77f336f87827e2cf5801305f075c45d7dd 添加默認 touchbar 文件,添加 最新 Touchbar 文件
d797ff57fd5ff74c233c804fb627c7df04456595 Update README.md
d8a1f7ea817a0aa51ff5b2c1f075e064a9a323f7 Merge branch 'master' of github.com:KyleBing/TouchbarBBT
f9075467294865fe1a31b0879aa2d11071fe1110 修改目錄名字,添加實際照片
51fde532cb2d1ef7197d14e66cdaaed46dc8be3a Create README.md
d0611a4e511641e772e56ec7c923291e254a54ad 初始化該倉庫,添加基礎的配置文件和基礎的圖標
git tag -a v1.2 51fde

共享標籤

git push 並不會把標籤傳送到遠程倉庫,顯式的推送纔會顯示。

git push origin v1.3

--tags 會把全部不在遠程服務器的標籤都推送到服務器上

git push origin --tags

刪除標籤

刪除本地標籤

git tag -d v1.3

檢出標籤

git checkout 2.0

Git 別名

git 能夠像系統那樣設置別名

git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git ci -m "infos"

# 跟下面做用同樣

git commit -m "infos"

分支

若是項目中新建了三個文件,在提交的時候,Git 倉庫中有五個對象:

  • 三個 blob 對象(保存着文件快照
  • 一個樹對象(記錄着目錄結構和 blob對象索引)
  • 一個提交對象(包含着指向前述樹對象的指針和全部提交信息)

clipboard.png

HEAD、 分支 master 是什麼東西

clipboard.png

git 的分支,實際上是指向不一樣提交版本的指針。在 git init 初始化的時候,默認生成了一個名爲 master 的分支,其實它跟其它分支的等級是同樣的,都只是一個分支,默認名爲 master,只是咱們都懶得給它更名罷了。

git 還有一個名爲 HEAD 的指針,做用是指向當前本地庫正在的修改的分支,如上圖,本地庫正在 master 分支上作修改。

建立分支

git branch testing

clipboard.png

上面的指令的結果如上圖,在當前版本上新建了一個名爲 testing 的分支。

git branch 只是建立一個分支,並不會切換到該分支。

分支切換

git checkout testing

上述操做會把 HEAD 指針指向 testing 分支,做用以下圖:

clipboard.png

當前在 testing 分支上,如今新建並提交一個文件,只會保存在 testing 分支上,而 master 分支還停留在前一個提交狀態上,也就是說該文件只存在於 testing 分支上。

效果以下圖;master 沒有動,testing 已經向前移動到了最新的節點。

切換分支的時候會改變本地的目錄結構

切換分支的時候,本地文件會變到當前分支的目錄結構上,若是因爲特殊緣由無法切換分支的時候,會提示切換分支失敗。

此時咱們再切換回 master 分支並作修改後提交,master 指針就會指向新的提交節點。此時,master testing 分別處於不一樣的提交節點上,以下圖:

clipboard.png

git log --online --graph --all

terminal 界面效果如圖:

clipboard.png

分支的新建與合併

工做中的常見情景:

  1. 開發一個項目
  2. 爲一個新的需求,建立一個分支,
  3. 在新建的分支上開展工做

正常開發過程當中,若是出現了一個嚴重問題,須要緊急修補,能夠這麼作:

  1. 切換到你線上的主分支
  2. 爲緊急任務新建一個分支,在這個分支上修復這個問題
  3. 在測試經過後,回到主分支上,並把解決問題的分支合併到主分支上
  4. 回到工做的分支,繼續工做

新建分支

若是項目已經有了必定的提交記錄,當前狀態是下面這樣:

clipboard.png

爲了修復一個問題編號是 #53 的問題,須要新建一個分支並在這個分支上開始修復工做

git checkout -b iss53

# 上面的命令是下面兩條指令的簡寫
git branch iss53
git checkout iss53

你已經在分支 iss53 上作了必定的修改並提交了,此時的倉庫是這樣的:

clipboard.png

此時,公司又有問題須要修改,沒必要把 iss53 和新問題混在一塊兒修改,直接在原有 master 分支上新建一個分支並在其上面修改便可。

# 切換到 master 分支
git checkout master

# 建立新問題分支 hotfix
git checkout -b hotfix

此時的倉庫狀態:

clipboard.png

這樣,你能夠在任意分支之間切換,且不會影響主分支 master 的正常運行。

假如,如今已經解決了主線上的問題,須要把 hotfix 分支合併到主線上。須要先切換到主分支 master 上,而後執行合併 hostfix 的操做

# 切到 master 分支
git checkout master

# 合併 hotfix 分支
git merge hotfix

# 結果
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

能夠看到反饋信息中的 fast-forward 提示,這是由於 hotfix 是在 master 分支新建的,並在其基礎上作的修改,他們的合併操做只須要 HEAD 指針執行簡單的前移便可,如圖:

clipboard.png

hotfix 問題解決併合併到主分支以後,你要回到以前的 iss53 分支繼續解決 #53 問題。在切回去以前,你應該先已合併的 hotfix 分支刪除,由於合併以後 masterhotfix 指向了同一個位置,已經不須要 hotfix了,執行操做:

# 刪除 hotfix 分支
git branch -d hotfix

倉庫如今是這樣的:

clipboard.png

分支的合併

通過奮力修改後,解決了 #53 問題,須要把 iss53 合併到 master 主分支中

# 切換到 master 主分支
git checkout master

# 合併 iss53 分支到 master
git merge iss53

# 結果
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

此次 merge 跟以前 hotfix 分支的合併並不同。這是由於,master 分支所在提交併非 iss53 分支所在提交的直接祖先,此時須要比對 master iss53 和 他們相交的 C2 進行合併:

clipboard.png

上面的合併後,倉庫是這樣的:

clipboard.png

合併後須要刪除無用的分支

git branch -d iss53

遇到衝突時的分支合併

若是前面提到的 iss53 hotfix 兩個分支都修改了同一個文件的同一個地方,那麼在合併的時候,git自動合併就會失敗,須要手動解決衝突:

# 合併 iss53
git merge iss53

# 結果
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

此時查看狀態會顯示有一個文件未合併(unmerged)

# 查看倉庫當前狀態
git status

# 結果
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:      index.html

no changes added to commit (use "git add" and/or "git commit -a")

出現衝突的時候,git 會在衝突文件中添加標準的衝突標記符,像下面這樣子:

clipboard.png

HEAD 所指示的版本在這個區段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 爲了解決衝突,你必須選擇使用由 ======= 分割的兩部分中的一個,或者你也能夠自行合併這些內容。 例如,你能夠經過把這段內容換成下面的樣子來解決衝突:

<div id="footer">
please contact us at email.support@github.com
</div>

解決衝突以後,用 git add 添加衝突文件到暫存區,此時 git 會認爲衝突已經解決,並移除衝突標記。

也能夠用圖形化的工具來解決衝突 git mergetool 會啓動合適的合併工具,其幫助信息以下:

git mergetool

This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.

# 這裏顯示支持的工具列表
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
Merging:
index.html

Normal merge conflict for 'index.html':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (opendiff):

此時查看狀態:

# 查看狀態
git status

# 結果
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

    modified:   index.html

完成提交:

# 執行提交
git commit

# 結果
「Merge branch 'iss53'

Conflicts:
    index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#    .git/MERGE_HEAD
# and try again.


# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#    modified:   index.html
#

分支管理

git branch 命令不僅是建立和刪除分支,不加參數時會列出全部分支

# 查看分支列表
git branch

# 結果
    iss53
*   master
    testing

* 表示當前 HEAD 指針的指向,也就是當前所處的分支。

查看每一個分支的最後一次提交:

# 查看分支最後提交
git branch -v

# 結果
  iss53   93b412c fix javascript issue
* master  7a98805 Merge branch 'iss53'
  testing 782fd34 add scott to the author list in the readmes

---gerged --no-merged 用於查看已合併的和未合併的分支

git branck --merged

# 結果
  iss53
* master

能夠看到當前 iss53 已合併到 master 中,能夠刪除 iss53 分支了。

當分支沒有合併時,執行刪除分支操做會失敗:

git branch -d testing

# 結果
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D testing'.

分支開發工做流

相關文章
相關標籤/搜索