Git版本控制 —— 經常使用命令目錄

本文使用命令和命令的基本含義做爲標題,旨在快速查找經常使用命令。git

 

環境配置

git config(配置文件設置)

Git 自帶一個 git config 的工具來幫助設置配置文件。github

這些變量存儲在三個不一樣的位置:web

/etc/gitconfig 文件: 包含系統上每個用戶及他們倉庫的通用配置。 若是使用帶有 --system選項的 git config 時,它會今後文件讀寫配置變量。shell

$ git config --system

~/.gitconfig 或 ~/.config/git/config 文件:只針對當前用戶。 能夠傳遞 --global 選項讓 Git 讀寫此文件。數據庫

$ git config --global

當前使用倉庫的 Git 目錄中的 config 文件(就是 .git/config):針對該倉庫。能夠傳遞 --local 選項讓 Git 讀寫此文件。服務器

$ git config --local

咱們也能夠不加參數表明從全部配置文件讀寫文件。app

$ git config

每個級別覆蓋上一級別的配置,覆蓋關係爲local > global > system.ssh

下面舉個例子:maven

-- 查看系統配置文件
$ git config --system --list

-- 查看用戶配置文件
$ git config --global --list

-- 查看項目配置文件
$ git config --local --list

-- 查看全部配置文件
$ git config --list

git config --list(查看配置文件)

此命令能夠配合配置文件標識查看不一樣級別配置文件內容編輯器

-- 查看系統配置文件
$ git config --system --list

-- 查看用戶配置文件
$ git config --global --list

-- 查看項目配置文件
$ git config --local --list

-- 查看全部配置文件
$ git config --list

git config <key> <value>(修改配置文件)

此命令用於修改配置文件內容。

可使用配置文件標識修改指定配置文件內容。

$ git config --global user.name "lic"

 

.gitignore文件(忽略提交)

通常咱們總會有些文件無需歸入 Git 的管理,也不但願它們總出如今未跟蹤文件列表。 一般都是些自動生成的文件,好比日誌文件,或者編譯過程當中建立的臨時文件等。 在這種狀況下,咱們能夠建立一個名爲.gitignore 的文件,列出要忽略的文件模式。

 例子忽略了IDEA、maven、日誌和svn生成的文件。

# --> IDEA
.idea/
*.iml

# --> maven
target/

# --> log
logs/

# --> svn
.svn/

 

基本操做

git help <verb>(獲取幫助)

使用此命令能夠獲取到git關於此命令的幫助手冊

$ git help config

 

git init (初始化倉庫)

若是你打算使用 Git 來對現有的項目進行管理,你只須要進入該項目目錄並輸入

$ git init

該命令將建立一個名爲 .git 的子目錄,這個子目錄含有你初始化的 Git 倉庫中全部的必須文件,這些文件是 Git 倉庫的骨幹。 

「.git」目錄中的文件結構以下

$ ls
config  description  HEAD  hooks/  info/  objects/  refs/
config git配置文件
description 倉庫的描述信息,主要給gitweb等git託管系統使用
HEAD 這個文件包含了一個檔期分支(branch)的引用
hooks/ 這個目錄存放一些shell腳本,能夠設置特定的git命令後觸發相應的腳本;在搭建gitweb系統或其餘git託管系統會常常用到hook script
info/ 包含倉庫的一些信息
objects/ 全部的Git對象都會存放在這個目錄中,對象的SHA1哈希值的前兩位是文件夾名稱,後38位做爲對象文件名
refs/ 這個目錄通常包括三個子文件夾,heads、remotes和tags,heads中的文件標識了項目中的各個分支指向的當前commit

 

git add<file name>(跟蹤文件、存入暫存區、標記已解決)

這是個多功能命令:能夠用它開始跟蹤新文件,或者把已跟蹤的文件放到暫存區,還能用於合併時把有衝突的文件標記爲已解決狀態等。 將這個命令理解爲「添加內容到下一次提交中」而不是「將一個文件添加到項目中」要更加合適。 

放在項目目錄下的文件默認狀況下是不受Git管理的,你可經過 git add 命令來實現對指定文件的跟蹤。

-- 添加某個文件
$ git add README.md

-- 添加所有文件(.爲通配符)
$ git add .

 

git clone <url>(克隆倉庫)

若是你想得到一份已經存在了的 Git 倉庫的拷貝,這是就要使用此命令。

這是 Git 區別於其它版本控制系統的一個重要特性,Git 克隆的是該 Git 倉庫服務器上的幾乎全部數據,而不是僅僅複製完成你的工做所須要文件。 當你執行 git clone命令的時候,默認配置下遠程 Git 倉庫中的每個文件的每個版本都將被拉取下來。 事實上,若是你的服務器的磁盤壞掉了,你一般可使用任何一個克隆下來的用戶端來重建服務器上的倉庫

Git 支持多種數據傳輸協議。  https:// 協議、 git:// 協議以及SSH協議。使用SSH協議時須要在遠程倉庫配置本機公鑰才能生效。

-- https協議
git clone https://git.oschina.net/imlichao/git-example.git

-- SSH協議
git clone git@git.oschina.net:imlichao/git-example.git

 

git status(查看文件狀態)

要查看哪些文件處於什麼狀態,能夠用此命令。 

$ git status

提示主要有一下幾部份內容:

-- 所在分支和跟蹤分支
On branch dev_5.2
Your branch is up-to-date with 'origin/dev_5.2'.

-- 沒有文件變動
nothing to commit, working tree clean

-- 未被Git管理文件(能夠git add添加跟蹤)
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        documents/new_file

nothing added to commit but untracked files present (use "git add" to track)

-- 沒有提保存暫存區的文件(能夠git add保存到暫存區、git checkout放棄修改、git commit -a直接提交)
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   README.md

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

-- 暫存區未提交的文件(能夠git reset HEAD返回工做區)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   README.md

-- 未推送到遠程分支的提交數量(能夠git push推送到遠程分支)
On branch dev_5.2
Your branch is ahead of 'origin/dev_5.2' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

git status --short(狀態簡覽)

git status 命令的輸出十分詳細,但其用語有些繁瑣。 若是你使用 git status -s 命令或 git status --short 命令,你將獲得一種更爲緊湊的格式輸出。 運行 git status -s ,狀態報告輸出以下:

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

新添加的未跟蹤文件前面有 ?? 標記,新添加到暫存區中的文件前面有 A 標記,修改過的文件前面有 M 標記。 你可能注意到了 M 有兩個能夠出現的位置,出如今右邊的 M 表示該文件被修改了可是還沒放入暫存區,出如今靠左邊的 M 表示該文件被修改了並放入了暫存區。 例如,上面的狀態報告顯示: README 文件在工做區被修改了可是尚未將修改後的文件放入暫存區,lib/simplegit.rb 文件被修改了並將修改後的文件放入了暫存區。 而 Rakefile 在工做區被修改並提交到暫存區後又在工做區中被修改了,因此在暫存區和工做區都有該文件被修改了的記錄。

 

git diff(差別比較)

咱們要比較工做區、暫存區以及倉庫分支中文件的差別時可使用此命令。

下面的命令若是不加<file name>表示比較全部文件差別

git diff <file name>(工做區與暫存區比較)

$ git diff README.md

git diff <branch name> <file name>(工做區與分支比較)

$ git diff dev_5.2 README.md

git diff --cached <file name>(暫存區與當前分支比較)

$ git diff --cached README.md

git diff --staged <file name>(暫存區與當前分支比較)

和--cached同樣兩種方式一種效果

$ git diff --staged README.md

git diff --cached <branch name><file name>(暫存區與其餘分支比較)

$ git diff --cached master README.md

git diff <branch name> <branch name><file name>(分支與分支比較)

$ git diff dev_5.2 master README.md

 

git commit(提交文件)

如今的暫存區域已經準備穩當能夠提交了。 在此以前,請必定要確認還有什麼修改過的或新建的文件尚未git add 過,不然提交的時候不會記錄這些還沒暫存起來的變化。 這些修改過的文件只保留在本地磁盤。 因此,每次準備提交前,先用 git status 看下,是否是都已暫存起來了, 而後再運行提交命令 git commit

git commit

這種方式會啓動文本編輯器以便輸入本次提交的說明。(提交說明必需要填)

git commit -m <commit message>(直接添加提交說明)

咱們也能夠直接使用 -m 參數直接填寫說明

git commit -m "commit explain"

git commit -a(跳過暫存區直接提交)

儘管使用暫存區域的方式能夠精心準備要提交的細節,但有時候這麼作略顯繁瑣。 Git 提供了一個跳過使用暫存區域的方式, 只要在提交的時候,給 git commit 加上 -a 選項,Git 就會自動把全部已經跟蹤過的文件暫存起來一併提交,從而跳過 git add 步驟:

$ git commit -a

 

git rm (刪除文件)

要從 Git 中移除某個文件,就必需要從已跟蹤文件清單中移除(確切地說,是從暫存區域移除),而後提交。 能夠用 git rm 命令完成此項工做,並連帶從工做目錄中刪除指定的文件,這樣之後就不會出如今未跟蹤文件清單中了。

$ git rm documents/test

因爲git rm是從暫存區域移除,回退操做要使用git reset HEAD從暫存區撤銷,再用git checkout -- 恢復工做區文件。若是已經提交可使用git reset進行回退。

-- 已刪除文件恢復到工做區
$ git reset HEAD documents/test
Unstaged changes after reset:
D       documents/test

-- 已刪除文件恢復到暫存區
$ git checkout -- documents/test

 

git mv <file path> <path>(移動文件)

文件file path移動到path目錄。

$ git mv documents/new ./

git mv <file name> <new name>(文件重命名)

文件名從file name更改成new name

$ git mv new new1

實際上至關於執行了如下操做

$ mv README.md README
$ git rm README.md
$ git add README

 

git log(查看提交歷史)

默認不用任何參數的話,git log 會按提交時間列出全部的更新,最近的更新排在最上面。 正如你所看到的,這個命令會列出每一個提交的 SHA-1 校驗和、做者的名字和電子郵件地址、提交時間以及提交說明。

git log -p(附帶內容差別)

此命令展現提交歷史時附帶內容差別

$ git log -p

git log --stat(附帶提交統計)

展現提交歷史時附帶統計信息。如那個文件變化幾行,增長內容仍是減小內容等信息。

git log --stat

git log --pretty=(指定顯示樣式)

這個選項能夠指定使用不一樣於默認格式的方式展現提交歷史。 這個選項有一些內建的子選項供你使用。 好比用 oneline 將每一個提交放在一行顯示,查看的提交數很大時很是有用。 另外還有 shortfull 和 fuller 能夠用,展現的信息或多或少有些不一樣,請本身動手實踐一下看看效果如何。

$ git log --pretty=oneline

git log --graph(分支合併線圖)

當 oneline 或 format 與另外一個 log 選項 --graph 結合使用時尤爲有用。 這個選項添加了一些ASCII字符串來形象地展現你的分支、合併歷史:

$ git log --graph

git log -- <file path>(某個文件的提交)

$ git log -- documents/test

git log -S <string>(變動了某些字符串的提交)

$ git log -S "git"

 

git cherry-pick <commit id>(選擇應用提交)

cherry-pick容許咱們提取一個或多個現有的提交,並使用這些提交的快照來建立新的提交。這個功能在處理生產bug時將會很是有用。

$ git cherry-pick 3016bb0b1a3deede145d5f93773ffc7928f22e73
[master 4aff2cc] experiment
 Date: Mon Apr 16 10:48:55 2018 +0800
 2 files changed, 3 insertions(+), 1 deletion(-)

因爲使用cherry-pick建立的提交標識名都是一致的,因此兩個應用了同一提交的分支在合併時並不會產生衝突,git會完美的將他處理成一次提交。

 

git reset HEAD^(版本回退)

將HEAD指針和當前分支指針回退一個提交版本。

一個「^」符號表明回退一個版本,三個就回退三個版本。

$ git reset HEAD^

git reset <commit id>(指定提交版本回退)

咱們能夠制定回退到某一次提交

$ git reset 3016bb0

 

git reflog(操做日誌)

此命令用於查看操做日誌。git全部的操做在這裏都能找到。

$ git reflog
3016bb0 (HEAD -> bug) HEAD@{0}: reset: moving to 3016bb0
5e96789 HEAD@{1}: reset: moving to HEAD^
3016bb0 (HEAD -> bug) HEAD@{2}: reset: moving to 3016bb0
3016bb0 (HEAD -> bug) HEAD@{3}: reset: moving to HEAD^
b5b1cff HEAD@{4}: checkout: moving from master to bug
6bef1e9 (master) HEAD@{5}: commit: experiment

若是咱們將已提交代碼進行了回退可是,發現回退錯了。這時候在 git log中是沒法找到記錄的。這是咱們就可使用reflog命令查找到那次提交記錄,而後用reset命令指定到回退前的提交編號。

以下圖:

 

撤銷操做

git checkout -- <file>...(撤銷工做區修改)

此命令使用了checkout其實真正的含義是,從上次提交的文件從新檢出。你須要知道 git checkout -- [file] 是一個危險的命令,這很重要。 你對那個文件作的任何修改都會消失 - 你只是拷貝了另外一個文件來覆蓋它。 除非你確實清楚不想要那個文件了,不然不要使用這個命令。

$ git checkout -- README.md

撤銷全部工做區修改

$ git checkout -- .

 

git reset HEAD <file>...(撤銷暫存文件)

文件從暫存區撤銷到工做區

$ git reset HEAD README.md
Unstaged changes after reset:
M       README.md

撤銷全部暫存區修改

$ git reset HEAD .

 

git commit --amend(從新提交)

有時候咱們提交完了才發現漏掉了幾個文件沒有添加,或者提交信息寫錯了。 此時,能夠運行帶有 --amend 選項的提交命令嘗試從新提交

$ git commit --amend

 這個命令會將暫存區中的文件提交。 若是自上次提交以來你還未作任何修改(例如,在上次提交後立刻執行了此命令),那麼快照會保持不變,而你所修改的只是提交信息。

 

儲藏場景

git stash(儲藏場景)

有時,當你在項目的一部分上已經工做一段時間後,全部東西都進入了混亂的狀態,而這時你想要切換到另外一個分支作一點別的事情。 問題是,你不想僅僅由於過會兒回到這一點而爲作了一半的工做建立一次提交。 針對這個問題的答案是 git stash 命令。

儲藏會處理工做目錄的髒的狀態 - 即,修改的跟蹤文件與暫存改動 - 而後將未完成的修改保存到一個棧上,而你能夠在任什麼時候候從新應用這些改動。

須要注意的是工做區和暫存區的代碼會所有被貯藏。

git stash

git stash save <message>(儲藏並添加註釋)

git stash save "stash註釋"

git stash list(查看儲藏列表)

$ git stash list
stash@{0}: WIP on master: 5e96789 experiment
stash@{1}: WIP on master: 5e96789 experiment
stash@{2}: On bug: Uncommitted changes before rebase

git stash apply <stash id>(恢復儲藏並保留)

若是想要應用其中一個更舊的儲藏,能夠經過名字指定它,像這樣:git stash apply stash@{2}。 若是不指定一個儲藏,Git 認爲指定的是最近的儲藏

恢復的時候若是不加參數將會將儲藏得全部內容恢復到工做區,若是增長了--index參數則會分別恢復到紅做區和暫存區。

$ git stash apply stash@{2}

git stash pop <stash id>(恢復儲藏並刪除)

就像apply同樣將內容恢復,可是回覆後的內容將從儲藏區刪除。

$ git stash pop stash@{2}

git stash clear(清空整個儲藏區)

將儲藏區全部內容所有清空,一旦清空這些代碼將永久丟失。因此要當心。

$ git stash clear

git stash drop <stash id> (刪除單個儲藏)

$ git stash drop <stash@{id}>

 

遠程倉庫

git remote(查看遠程倉庫)

若是想查看你已經配置的遠程倉庫服務器,能夠運行 git remote 命令。 它會列出你指定的每個遠程服務器的簡寫。 若是你已經克隆了本身的倉庫,那麼至少應該能看到 origin - 這是 Git 給你克隆的倉庫服務器的默認名字

$ git remote
origin

你也能夠指定選項 -v,會顯示須要讀寫遠程倉庫使用的 Git 保存的簡寫與其對應的 URL。 

$ git remote -v
origin  ssh://git@192.168.17.247:10022/PL_service_department/pmall.git (fetch)
origin  ssh://git@192.168.17.247:10022/PL_service_department/pmall.git (push)

git remote add <shortname> <url>(添加遠程倉庫)

建立一個新的遠程倉庫

$ git remote add pb https://github.com/paulboone/ticgit

git remote rename <remote-name><new remote-name>(遠程倉庫重命名)

$ git remote rename origin origin1

git remote rm <remote-name>(刪除遠程倉庫)

git remote rm origin1

 

git fetch(從遠程倉庫拉取)

這個命令會訪問遠程倉庫,從中拉取全部你尚未的數據。 執行完成後,你將會擁有那個遠程倉庫中全部分支的引用,能夠隨時合併或查看。

必須注意 git fetch 命令會將數據拉取到你的本地倉庫 - 它並不會自動合併或修改你當前的工做。 當準備好時你必須手動將其合併入你的工做。

$ git fetch

此命令是倉庫級別的,fatch會將全部分支的變動都拉下來。

git fetch <remote-name>(指定遠程倉庫拉取)

指定拉取代碼的倉庫名稱

$ git fetch origin

 

git pull(拉取遠程倉庫&合併遠程分支)

從遠程倉庫拉取變動並自動合併當前分支。pull命令會先執行fetch命令將遠程倉庫的變動拉取到本地,而後嘗試將當前分支與對應的跟蹤分支進行merge合併。

$ git pull

這裏注意fatch是倉庫級別的而pull是分支級別的。

git pull --rebase(拉取遠程倉庫&變基遠程分支)

當咱們但願拉取分支後執行的不是merge而是rebase時咱們可使用此命令

git pull --rebase

咱們也能夠修改配置文件讓pull默認執行rebase

git config --global pull.rebase true

git pull <remote-name> <branch-name>(指定拉取合併遠程分支)

拉取後與指定分支進行合併

$ git pull origin dev_5.3

 

git push(推送到遠程分支)

當你想分享你的項目時,必須將其推送到遠程分支。此命令將當前分支推送至跟蹤的遠程分支。

git push

這裏注意fatch是倉庫級別的而push是分支級別的。

git push <remote-name> <branch-name>(指定遠程分支推送)

當前分支推送到指定的分支

git push origin master

git push <remote-name> <branch-name>:<origin branch-name>(指定遠程分支推送)

當本地分支與遠程分支不一樣名時使用此命令

git push origin mymaster:master

git push -u <remote-name><branch name>(建立遠程分支)

將本地建立的分支推送到遠程倉庫

git push -u origin <branch name>

-u 表示添加本地分支與遠程分支的跟蹤分支。

git push -u <remote-name><branch name>:<origin branch name>(建立遠程分支)

咱們也能夠建立與本地分支不一樣名的遠程分支

git push -u origin mymaster:master

git push <remote-name>--delete <branch-name>(刪除遠程分支)

git push origin --delete serverfix

git push <remote-name> :<origin branch name>(刪除遠程分支)

將一個空分支推送給遠程分支實現刪除操做。

git push origin :master

 

標籤管理

git tag(查看標籤)

這個命令以字母順序列出標籤;可是它們出現的順序並不重要。

$ git tag

git tag -n(查看標籤帶註釋)

$ git tag -n

git tag -l(篩選標籤)

你也可使用特定的模式查找標籤。 例如,Git 自身的源代碼倉庫包含標籤的數量超過 500 個。 若是隻對 1.8.5 系列感興趣,能夠運行:

$ git tag -l 'v1.8.5*'

git tag <tag name>(建立輕量標籤)

一個輕量標籤很像一個不會改變的分支 - 它只是一個特定提交的引用。與svn不一樣git的標籤是不能夠移動的。

$ git tag v6.0

git tag -a <tag name> -m <message>(建立附註標籤)

附註標籤是存儲在 Git 數據庫中的一個完整對象。 它們是能夠被校驗的;其中包含打標籤者的名字、電子郵件地址、日期時間;還有一個標籤信息;而且可使用 GNU Privacy Guard (GPG)簽名與驗證。

$ git tag -a v1.4 -m 'my version 1.4'

 git tag -a <tag name> <commit id>(歷史提交上打標籤)

你也能夠對過去的提交打標籤。

$ git tag -a v1.2 9fceb02

git tag -d <tag name>(刪除標籤)

$ git tag -d v6.0
Deleted tag 'v6.0' (was e26bdca)

git push origin <tag_name>(標籤推送到遠程倉庫)

$ git push origin v5.5

git push origin --tags(全部標籤推送到遠程倉庫)

$ git push origin --tags

git push <remote-name> :<origin tag name>(刪除遠程標籤)

將一個空標籤推送給遠程分支實現刪除操做。

git push origin :v1.0.0

git checkout -b <branch_name> <tag_name>(從標籤檢出分支)

git checkout -b master v6.0

 

分支管理

git branch(查看分支)

$ git branch
  dev_5.2
* master

git branch <branch name>(建立分支)

建立分支時會在當前所在的提交對象上建立一個指針。

建立分支時很容易被理解成從當前分支建立一個分支,其實git並無考慮分支之間的關係。只不過當前分支也湊巧指向了當前所在的提交,因此只是建立了指向當前提交的指針與其它分支無關。

git branch -d <branch name>(刪除分支)

git branch -d hotfix

git branch -v (查看分支附帶最後一次提交)

$ git branch -v
* bug1    fe13e9b 生產環境修改一個bug
  dev_5.2 fe13e9b [ahead 5] 生產環境修改一個bug
  master  fe13e9b [ahead 5] 生產環境修改一個bug

git branch -vv (查看分支附帶跟蹤分支)

從遠程分支建立的本地分支,都會自動建立一個跟蹤分支來維護本地分支與遠程分支的對應關係。

咱們在pull或push代碼時就會與對應的遠程分支進行交互。

$ git branch -vv
* bug1    fe13e9b 生產環境修改一個bug
  dev_5.2 fe13e9b [origin/dev_5.2: ahead 5] 生產環境修改一個bug
  master  fe13e9b [origin/master: ahead 5] 生產環境修改一個bug

這會將全部的本地分支列出來而且包含更多的信息,如每個分支正在跟蹤哪一個遠程分支與本地分支是不是領先、落後或是都有。

git branch --set-upstream-to=<remote branch>(指定跟蹤分支)

咱們想本身指定本地分支的遠程跟蹤分支時使用此命令

$ git branch --set-upstream-to=origin/dev_5.2
Branch bug1 set up to track remote branch dev_5.2 from origin.

git branch -a (查看所有分支包括遠程分支)

$ git branch -a
* bug1
  dev_5.2
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev_5.2
  remotes/origin/master

 git branch --merged(已合併到當前分支的分支) 

$ git branch --merged

git branch --no-merged(未合併到當前分支的分支) 

$ git branch --no-merged

 

git checkout <branch name>(分支切換)

Git有一個名爲HEAD的特殊指針,指向當前所在的本地分支(譯註:將 HEAD 想象爲當前分支的別名)。

切換分支就是將HEAD指針指向目標分支而已。

git checkout testing

分支切換會改變你工做目錄中的文件

在切換分支時,必定要注意你工做目錄裏的文件會被改變。 若是是切換到一個較舊的分支,你的工做目錄會恢復到該分支最後一次提交時的樣子。 若是 Git 不能幹淨利落地完成這個任務,它將禁止切換分支。

git checkout -b <branch name>(建立並切換分支)

想要新建一個分支並同時切換到那個分支上,你能夠運行一個帶有 -b 參數的 git checkout 命令

$ git checkout -b bug1
Switched to a new branch 'bug1'

git checkout -b <branch name> <remote  branch>(從遠程分支建立並切換分支)

$ git checkout -b master1 origin/master
Switched to a new branch 'master1'
Branch master1 set up to track remote branch master from origin.

 

git merge <branch name>(分支合併)

咱們想將出現分叉提交的分支整合在一塊兒時,可使用合併(merge)操做來完成。

Git 會使用兩個分支的末端所指的快照以及這兩個分支的工做祖先,作一個簡單的三方合併。

$ git merge hotfix

快進合併(fast-forward)

當你試圖合併兩個分支時,若是順着一個分支走下去可以到達另外一個分支,那麼 Git 在合併二者的時候,只會簡單的將指針向前推動(指針右移),由於這種狀況下的合併操做沒有須要解決的分歧——這就叫作 「快進(fast-forward)」。

master只要向前推動就能夠完成與iss53的合併,因此會使用快進合併。

遇到衝突時的分支合併

有時候合併操做不會如此順利。 若是你在兩個不一樣的分支中,對同一個文件的同一個部分進行了不一樣的修改,Git 就無法乾淨的合併它們。在合併它們的時候就會產生合併衝突。

解決衝突步驟:

一、須要手動解決衝突並標記已解決。

$ git add README.md

二、須要本身提交新的合併提交。

$ git commit

 

git rebase <branch name>(變基)

你能夠提取在一個分支中引入的補丁和修改,而後在另外一個分支的基礎上應用一次。 在 Git 中,這種操做就叫作 變基

Git變基時咱們要分清,那個分支產生了補丁,那個分支是基底分支。

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: experiment

上例的當前分支(experiment)爲補丁分支,rebase後面跟基底分支(master)。也就是說用experiment分支的提交建立補丁,在master分支上從新執行一遍。

從上圖能夠看出,分叉提交C4不見了,在C3後面從新提交了C4'。master基底分支指針不移動,experiment補丁分支指針指向C4'。

最後若是咱們想要讓master分支指針也指向最新提交C4',咱們能夠切換到master分支執行快進合併(fast-forward)。

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
  (use "git push" to publish your local commits)


$ git merge experiment
Updating 4f3f69a..373256b
Fast-forward
 README.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

git rebase --onto <base branch> [<upstream> [<branch>]](指定補丁分支變基)

咱們能夠指定補丁分支變基到基底分支上。

$ git rebase master experiment
First, rewinding head to replay your work on top of it...
Applying: experiment

還有一種更加複雜的用法。從master分支建立server分支,從server分支建立client分支。

若是咱們想將client相對於server的不一樣提交變基到,master上咱們能夠這樣使用。

$ git rebase --onto master server client

 git rebase (--continue | --abort | --skip)(變基繼續、終止、跳過)

在變基時若是發現補丁分支快照與基底分支快照存在衝突,變基會中止而且要求手動解決衝突。

變基中止時咱們可使用--continue | --abort | --skip參數來控制變基行爲。

$ git rebase --continue

處理完衝突後使用此命令繼續變基

$ git rebase --abort

放棄本次變基,還原成變基以前的樣子

$ git rebase --skip

放棄補丁版本快照,繼續使用基底版本快照。

git rebase -i (交互式變基)

交互式變基使用屢次提交,從新創建提交。提交重建範圍爲沒有push到遠程分支的提交。

$git rebase -i

如今咱們要對每次提交設置命令。通常的合併咱們會將第一次提交選擇爲pick然後面的提交選擇爲squash。這樣就會用全部的提交生成一次新的提交。 

pick 4f3f69a experiment
pick 373256b experiment
pick 3258dad experiment
pick 167f684 experiment
pick cd871a6 experiment
pick d06c0a0 experiment
pick 9f3e252 experiment

# Rebase 1221f68..9f3e252 onto 1221f68 (12 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

而後系統提示從新編輯提交說明。(被合併的提交說明會默認按順序添加)

最後咱們使用git log查看提交日誌發現已經剩下一次提交了。

git rebase -i HEAD^^^(交互變基指定提交次數)

咱們在進行交互式變基的時候能夠指定變基提交的次數。HEAD參數後面每增長一個「^」符號表明向後提取一次分支。

$ git rebase -i HEAD^^^^^

這個命令表明從當前提交向後獲取5次提交進行交互式變基。

相關文章
相關標籤/搜索