1. 程式人生 > >版本控制工具Git

版本控制工具Git

1、 版本控制基礎

1.1什麼是版本控制工具git?

1) Git是一個開源的分散式版本控制系統。

2)與SVN,CVS相比, Git不需要中心倉庫

3)Git的分支與合併比較簡單,版本對比快

4)GitHub是一個基於web與Git的一個專案託管服務平臺,要求原始碼必須公開

5)GitLab是一個用於倉庫管理的開源專案,使用Git作為程式碼管理工具,可以部署在本地或私有伺服器上

1.2 版本控制基本概念

1)Repository(本地庫和遠端庫)

2)Pull/Push/Checkout/Feteh

3)  Branch

4)  Merge

5)  Conflict

6)  Revert

7)  Working Directory

1.2.1 git檔案的狀態變化

檔案的三種狀態:

已提交(committed),已修改(modified,已暫存(staged)

 

1)   工作目錄下的檔案有兩種狀態:已跟蹤或未跟蹤(tracked or untracked)

2)   已跟蹤的檔案是指已被納入版本控制管理的檔案,在上次快照中有他們的記錄,工作一段時間以後,工作一段時間後,它們的狀態可能是未更新,已修改或已放入暫存區

3)   未跟蹤的檔案是指沒有納入版本控制的檔案,它們既沒有上次更新時的快照,也不在當前的暫存區

4)   初次克隆某個版本倉庫時,工作目錄中的所有檔案都屬於已跟蹤檔案,且狀態為未修改

5)   通過git add將檔案改為statged狀態

6)   檔案修改了後提交時加-a來載入

1.3 Git常用命令

1.3.1獲得倉庫

1)   Git init

2)   Git clone

3)   Git pull與git fetch的區別

4)   Get fetch從遠端獲取最新版本到本地,不會自動merge

5)   Git pull 從遠端獲取最新版本並merge 到本地,相當於git fetch + Git merge

1.3.2 記錄每次更新到倉庫

l  Git status 檢視當前檔案狀態

l  Git add 跟蹤新檔案, 暫存已修改過的檔案

l  Gitdiff,Git diff –staged 檢視已暫存和未暫存的更新

l  Git commit –m “更新說明”

l  Git commit –a 跳過使用暫存區

l  Git rm 移除檔案

l  Git mv 移動檔案

1.3.3 獲取資訊

1)get help

2) git status

3) git diff

4) git log 檢視提交歷史

5) git show

1.3.4 分支與標記

l  建立分支

Git branch <name>

Git branch <name> <commit-id>

l  刪除分支

Git branch –d <name>

l  檢視分支

Git branch

Git branch –r 檢視遠端伺服器上的分支

l  轉移到某個分支

Git checkout <commit-id>

Git checkout –b <name><commit-id>

l  分支合併

Git merge <name> 合併制定分支到當前分支

l  標記

標記用於標識某次比較重要的提交

Git tag <tag-name>

1.3.5 版本恢復

l  Reset

將當前的工作目錄完全回滾到指定的版本號

l  Revert

還原一個版本的修改,必須提供一個具體的git版本號

例如 git revert bbaf6f

l  Reset 和Revert的區別

Reset是將當前head的內容重置,不會留任何痕跡

Revert是撤銷某次提交,但是這次撤銷也會作為一次提交進行儲存

 

1.3.6 插銷操作

Git commit –amend 修改最後一次提交

Git reset HEAD <file> 取消已經暫存的檔案

Git checkout --<file> 取消對檔案的修改

 

1.3.7遠端倉庫的使用

Git remote 檢視當前的遠端庫

Git remote add新增遠端倉庫

Git fetch [remote –name] 從遠端倉庫抓取資料

Git push [remote –name] 推送資料到遠端倉庫

Git remote show [remote –name] 檢視遠端倉庫資訊

 

1.4 Git命令圖解

1.5 Git的工作流程

l  與遠端倉庫同步(pull,fetch)

l  修改檔案

l  檢視變更(show,status)

l  載入變更(add or-a)

l  提交載入的變更(commit)

l  重複

l  上傳(push)

1.6 Git的分支

1.6.1 分支的概念

分支是指在軟體開發中每個開發人員在已有版本的基礎上按照各自任務的不同建立個人的軟體庫副本,每個人可以互不影響地工作在自己的副本里,等工作完成後再把工作成果提交到公共的軟體庫,如果有衝突,就解決衝突後再提交。

幾乎所有的版本控制系統都以某種形式支援分支。 使用分支意味著你可以把你的工作從開發主線上分離開來,以免影響開發主線。

1.6.2 Git分支簡介

假設現在有一個工作目錄,裡面包含了三個將要被暫存和提交的檔案。 暫存操作會為每一個檔案計算校驗和(使用SHA-1 雜湊演算法),然後會把當前版本的檔案快照儲存到 Git 倉庫中(Git 使用 blob 物件來儲存它們),最終將校驗和加入到暫存區域等待提交:

git add README test.rb
git commit -m 'The initial commit of my project'
當使用 git commit 進行提交操作時,Git 會先計算每一個子目錄(本例中只有專案根目錄)的校驗和,然後在 Git 倉庫中這些校驗和儲存為樹物件。 隨後,Git 便會建立一個提交物件,它除了包含上面提到的那些資訊外,還包含指向這個樹物件(專案根目錄)的指標。如此一來,Git 就可以在需要的時候重現此次儲存的快照。

現在,Git 倉庫中有五個物件:三個 blob 物件(儲存著檔案快照)、一個樹物件(記錄著目錄結構和 blob 物件索引)以及一個提交物件(包含著指向前述樹物件的指標和所有提交資訊)。

Figure 1-1. 首次提交物件及其樹結構

做些修改後再次提交,那麼這次產生的提交物件會包含一個指向上次提交物件(父物件)的指標。

Figure 1-2. 提交物件及其父物件

Git 的分支,其實本質上僅僅是指向提交物件的可變指標。 Git 的預設分支名字是 master。 在多次提交操作之後,你其實已經有一個指向最後那個提交物件的 master 分支。 它會在每次的提交操作中自動向前移動。

Figure 1-3. 分支及其提交歷史

 

1.6.3 分支的建立

Git建立新分支的方式很簡單,它只是為你建立了一個可以移動的新的指標。 比如,建立一個testing 分支, 你需要使用 git branch 命令:

git branch testing

Figure1-4. 兩個指向相同提交歷史的分支

Git 通過HEAD確定當前在哪一個分支上工作, HEAD 是一個特殊指標。 請注意它和許多其它版本控制系統(如 Subversion 或 CVS)裡的 HEAD 概念完全不同。 在 Git 中,它是一個指標,指向當前所在的本地分支(譯註:將 HEAD 想象為當前分支的別名)。 在本例中,你仍然在 master 分支上。 因為 git branch 命令僅僅 建立 一個新分支,並不會自動切換到新分支中去。

Figure 1-5. HEAD 指向當前所在的分支

可以簡單地使用 git log 命令檢視各個分支當前所指的物件。 提供這一功能的引數是 --decorate

$ git log --oneline --decorate
f30ab (HEAD, master, testing) add feature #32 - ability to add new
34ac2 fixed bug #1328 - stack overflow under certain conditions
98ca9 initial commit of my project

1.6.4分支切換

要切換到一個已存在的分支,你需要使用 git checkout 命令。 我們現在切換到新建立的 testing 分支去:

$ git checkout testing

這樣 HEAD 就指向 testing 分支了。

Figure 1-6. HEAD 指向當前所在的分支

這種切換分支有什麼實質意義呢? 現在不妨再提交一次:

$ vim test.rb
$ git commit -a -m 'made a change'

Figure 1-7. HEAD 分支隨著提交操作自動向前移動

如圖所示,你的 testing 分支向前移動了,但是 master 分支卻沒有,它仍然指向執行 git checkout 時所指的物件。 這就有意思了,現在我們切換回 master 分支看看:

$ git checkout master

Figure 1-8. 檢出時 HEAD 隨之移動

這條命令做了兩件事。 一是使 HEAD 指回 master 分支,二是將工作目錄恢復成 master 分支所指向的快照內容。 也就是說,你現在做修改的話,專案將始於一個較舊的版本。 本質上來講,這就是忽略 testing 分支所做的修改,以便於向另一個方向進行開發。

分支切換會改變你工作目錄中的檔案

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

如果你在當前分支進行修改和提交:

$ vim test.rb
$ git commit -a -m 'made other changes'
現在,這個專案的提交歷史已經產生了分叉(參見下圖 Figure1-9)。 因為剛才你建立了一個新分支,並切換過去進行了一些工作,隨後又切換回 master 分支進行了另外一些工作。 上述兩次改動針對的是不同分支:你可以在不同分支間不斷地來回切換和工作,並在時機成熟時將它們合併起來。 而所有這些工作,你需要的命令只有 branchcheckoutcommit
 
 

你可以簡單地使用 git log 命令檢視分叉歷史。 執行 git log --oneline --decorate --graph --all ,它會輸出你的提交歷史、各個分支的指向以及專案的分支分叉情況。

$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project

由於 Git 的分支實質上僅是包含所指物件校驗和(長度為 40 的 SHA-1 值字串)的檔案,所以它的建立和銷燬都異常高效。 建立一個新分支就像是往一個檔案中寫入 41 個位元組(40 個字元和 1 個換行符),如此的簡單能不快嗎?

這與過去大多數版本控制系統形成了鮮明的對比,它們在建立分支時,將所有的專案檔案都複製一遍,並儲存到一個特定的目錄。 完成這樣繁瑣的過程通常需要好幾秒鐘,有時甚至需要好幾分鐘。所需時間的長短,完全取決於專案的規模。而在 Git 中,任何規模的專案都能在瞬間建立新分支。 同時,由於每次提交都會記錄父物件,所以尋找恰當的合併基礎(譯註:即共同祖先)也是同樣的簡單和高效。 這些高效的特性使得 Git 鼓勵開發人員頻繁地建立和使用分支。

1.6.5 分支建立和合並(實際例子)

讓我們來看一個簡單的分支新建與分支合併的例子,實際工作中你可能會用到類似的工作流。 你將經歷如下步驟:

1.  開發某個網站。

2.  為實現某個新的需求,建立一個分支。

3.  在這個分支上開展工作。

正在此時,你突然接到一個電話說有個很嚴重的問題需要緊急修補。 你將按照如下方式來處理:

1.  切換到你的線上分支(production branch)。

2.  為這個緊急任務新建一個分支,並在其中修復它。

3.  在測試通過之後,切換回線上分支,然後合併這個修補分支,最後將改動推送到線上分支。

4.  切換回你最初工作的分支上,繼續工作。

   1.6.5.1新建分支

首先,我們假設你正在你的專案上工作,並且已經有一些提交。

                                 Figure 1-10. 一個簡單提交歷史

現在,你已經決定要解決你的公司使用的問題追蹤系統中的 #53 問題。 想要新建一個分支並同時切換到那個分支上,你可以執行一個帶有 -b 引數的 git checkout 命令:

$ git checkout -b iss53
Switched to a new branch "iss53"

它是下面兩條命令的簡寫:

$ git branch iss53
$ git checkout iss53

Figure 1-11. 建立一個新分支指標

你繼續在 #53 問題上工作,並且做了一些提交。 在此過程中,iss53 分支在不斷的向前推進,因為你已經檢出到該分支(也就是說,你的 HEAD 指標指向了 iss53 分支)

$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'

Figure 1-12. iss53 分支隨著工作的進展向前推進

現在你接到那個電話,有個緊急問題等待你來解決。 有了 Git 的幫助,你不必把這個緊急問題和 iss53 的修改混在一起,你也不需要花大力氣來還原關於 53# 問題的修改,然後再新增關於這個緊急問題的修改,最後將這個修改提交到線上分支。 你所要做的僅僅是切換回 master 分支。

但是,在你這麼做之前,要留意你的工作目錄和暫存區裡那些還沒有被提交的修改,它可能會和你即將檢出的分支產生衝突從而阻止 Git 切換到該分支。 最好的方法是,在你切換分支之前,保持好一個乾淨的狀態。 有一些方法可以繞過這個問題(即,儲存進度(stashing) 和 修補提交(commit amending))。 現在,我們假設你已經把你的修改全部提交了,這時你可以切換回 master 分支了:

$ git checkout master
Switched to branch 'master'

這個時候,你的工作目錄和你在開始 #53 問題之前一模一樣,現在你可以專心修復緊急問題了。 請牢記:當你切換分支的時候,Git 會重置你的工作目錄,使其看起來像回到了你在那個分支上最後一次提交的樣子。 Git 會自動新增、刪除、修改檔案以確保此時你的工作目錄和這個分支最後一次提交時的樣子一模一樣。

接下來,你要修復這個緊急問題。 讓我們建立一個針對該緊急問題的分支(hotfix branch),在該分支上工作直到問題解決:

$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix 1fb7853] fixed the broken email address
 1 file changed, 2 insertions(+)

Figure 1-13. 基於 master 分支的緊急問題分支 hotfix branch

你可以執行你的測試,確保你的修改是正確的,然後將其合併回你的 master 分支來部署到線上。 你可以使用 git merge 命令來達到上述目的:

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

在合併的時候,你應該注意到了"快進(fast-forward)"這個詞。 由於當前 master 分支所指向的提交是你當前提交(有關 hotfix 的提交)的直接上游,所以 Git 只是簡單的將指標向前移動。 換句話說,當你試圖合併兩個分支時,如果順著一個分支走下去能夠到達另一個分支,那麼 Git 在合併兩者的時候,只會簡單的將指標向前推進(指標右移),因為這種情況下的合併操作沒有需要解決的分歧——這就叫做 “快進(fast-forward)”。

現在,最新的修改已經在 master 分支所指向的提交快照中,你可以著手釋出該修復了。

Figure 1-14. master 被快進到 hotfix

關於這個緊急問題的解決方案發布之後,你準備回到被打斷之前時的工作中。 然而,你應該先刪除 hotfix 分支,因為你已經不再需要它了 —— master 分支已經指向了同一個位置。 你可以使用帶 -d 選項的 git branch 命令來刪除分支:

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

現在你可以切換回你正在工作的分支繼續你的工作,也就是針對 #53 問題的那個分支(iss53 分支)。

$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)

Figure 3-15. 繼續在 iss53 分支上的工作

你在 hotfix 分支上所做的工作並沒有包含到 iss53 分支中。 如果你需要拉取 hotfix 所做的修改,你可以使用 git merge master 命令將 master 分支合併入 iss53 分支,或者你也可以等到 iss53 分支完成其使命,再將其合併回 master 分支。

1.6.5.2分支的合併

假設你已經修正了 #53 問題,並且打算將你的工作合併入 master 分支。 為此,你需要合併 iss53 分支到 master 分支,這和之前你合併 hotfix 分支所做的工作差不多。 你只需要檢出到你想合併入的分支,然後執行 git merge 命令:

$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

這和你之前合併 hotfix 分支的時候看起來有一點不一樣。 在這種情況下,你的開發歷史從一個更早的地方開始分叉開來(diverged)。 因為,master 分支所在提交併不是 iss53 分支所在提交的直接祖先,Git 不得不做一些額外的工作。 出現這種情況的時候,Git 會使用兩個分支的末端所指的快照(C4 和 C5)以及這兩個分支的工作祖先(C2),做一個簡單的三方合併。

Figure 1-16. 一次典型合併中所用到的三個快照

和之前將分支指標向前推進所不同的是,Git 將此次三方合併的結果做了一個新的快照並且自動建立一個新的提交指向它。 這個被稱作一次合併提交,它的特別之處在於他有不止一個父提交。

Figure 1-17. 一個合併提交

需要指出的是,Git 會自行決定選取哪一個提交作為最優的共同祖先,並以此作為合併的基礎;這和更加古老的 CVS 系統或者 Subversion (1.5 版本之前)不同,在這些古老的版本管理系統中,使用者需要自己選擇最佳的合併基礎。 Git 的這個優勢使其在合併操作上比其他系統要簡單很多。

既然你的修改已經合併進來了,你已經不再需要 iss53 分支了。 現在你可以在任務追蹤系統中關閉此項任務,並刪除這個分支。

$ git branch -d iss53

1.6.5.3 遇到衝突時的分支合併

有時候合併操作不會如此順利。 如果你在兩個不同的分支中,對同一個檔案的同一個部分進行了不同的修改,Git 就沒法乾淨的合併它們。 如果你對 #53 問題的修改和有關 hotfix 的修改都涉及到同一個檔案的同一處,在合併它們的時候就會產生合併衝突:

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

此時 Git 做了合併,但是沒有自動地建立一個新的合併提交。 Git 會暫停下來,等待你去解決合併產生的衝突。 你可以在合併衝突後的任意時刻使用 git status 命令來檢視那些因包含合併衝突而處於未合併(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 會在有衝突的檔案中加入標準的衝突解決標記,這樣你可以開啟這些包含衝突的檔案然後手動解決衝突。 出現衝突的檔案會包含一些特殊區段,看起來像下面這個樣子:

<<<<<<< HEAD:index.html
<div id="footer">contact : [email protected]</div>
=======
<div id="footer">
 please contact us at [email protected]
</div>
>>>>>>> iss53:index.html

這表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因為你在執行 merge 命令的時候已經檢出到了這個分支)在這個區段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 為了解決衝突,你必須選擇使用由 ======= 分割的兩部分中的一個,或者你也可以自行合併這些內容。 例如,你可以通過把這段內容換成下面的樣子來解決衝突:

<div id="footer">
please contact us at [email protected]
</div>

上述的衝突解決方案僅保留了其中一個分支的修改,並且 <<<<<<< , ======= , 和 >>>>>>>這些行被完全刪除了。 在你解決了所有檔案裡的衝突之後,對每個檔案使用 git add 命令來將其標記為衝突已解決。 一旦暫存這些原本有衝突的檔案,Git 就會將它們標記為衝突已解決。

你可以再次執行 git status 來確認所有的合併衝突都已被解決:

$ 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
#

如果你覺得上述的資訊不夠充分,不能完全體現分支合併的過程,你可以修改上述資訊,新增一些細節給未來檢視這個合併的讀者一些幫助,告訴他們你是如何解決合併衝突的,以及理由是什麼。

1.6.6 分支的管理

現在已經建立、合併、刪除了一些分支,讓我們看看一些常用的分支管理工具。

git branch 命令不只是可以建立與刪除分支。 如果不加任何引數執行它,會得到當前所有分支的一個列表:

$ git branch
  iss53
* master
  testing

注意 master 分支前的 * 字元:它代表現在檢出的那一個分支(也就是說,當前 HEAD 指標所指向的分支)。 這意味著如果在這時候提交,master 分支將會隨著新的工作向前移動。 如果需要檢視每一個分支的最後一次提交,可以執行 git branch -v 命令:

$ git branch -v
  iss53   93b412c fix javascript issue
* master  7a98805 Merge branch 'iss53'
  testing 782fd34 add scott to the author list in the readmes

--merged 與 --no-merged 這兩個有用的選項可以過濾這個列表中已經合併或尚未合併到當前分支的分支。 如果要檢視哪些分支已經合併到當前分支,可以執行 git branch --merged

$ git branch --merged
  iss53
* master

因為之前已經合併了 iss53 分支,所以現在看到它在列表中。 在這個列表中分支名字前沒有 * 號的分支通常可以使用 git branch -d 刪除掉;你已經將它們的工作整合到了另一個分支,所以並不會失去任何東西。

檢視所有包含未合併工作的分支,可以執行 git branch --no-merged

$ git branch --no-merged
  testing

這裡顯示了其他分支。 因為它包含了還未合併的工作,嘗試使用 git branch -d 命令刪除它時會失敗:

$ 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'.

如果真的想要刪除分支並丟掉那些工作,如同幫助資訊裡所指出的,可以使用 -D 選項強制刪除它。

1.6.7 分支開發流程

由於分支管理的便捷,已經衍生出一些典型的工作模式,我們可以根據專案實際情況選擇一種實用。

1.6.7.1 長期分支模式

因為 Git 使用簡單的三方合併,所以就算在一段較長的時間內,反覆把一個分支合併入另一個分支,也不是什麼難事。 也就是說,在整個專案開發週期的不同階段,你可以同時擁有多個開放的分支;你可以定期地把某些特性分支合併入其他分支中。

許多使用 Git 的開發者都喜歡使用這種方式來工作,比如只在 master 分支上保留完全穩定的程式碼——有可能僅僅是已經發布或即將釋出的程式碼。 他們還有一些名為 develop 或者 testing 的平行分支,被用來做後續開發或者測試穩定性——這些分支不必保持絕對穩定,但是一旦達到穩定狀態,它們就可以被合併入 master 分支了。 這樣,在確保這些已完成的特性分支(短期分支,比如之前的 iss53 分支)能夠通過所有測試,並且不會引入更多 bug 之後,就可以合併入主幹分支中,等待下一次的釋出。

事實上我們剛才討論的,是隨著你的提交而不斷右移的指標。 穩定分支的指標總是在提交歷史中落後一大截,而前沿分支的指標往往比較靠前。

Figure 1-18. 漸進穩定分支的線性圖

通常把他們想象成流水線(work silos)可能更好理解一點,那些經過測試考驗的提交會被遴選到更加穩定的流水線上去。

Figure 1-19. 漸進穩定分支的流水線(“silo”)檢視

可以用這種方法維護不同層次的穩定性。 一些大型專案還有一個 proposed(建議) 或 pu: proposed updates(建議更新)分支,它可能因包含一些不成熟的內容而不能進入 next 或者 master 分支。 這麼做的目的是使你的分支具有不同級別的穩定性;當它們具有一定程度的穩定性後,再把它們合併入具有更高級別穩定性的分支中。 再次強調一下,使用多個長期分支的方法並非必要,但是這麼做通常很有幫助,尤其是當你在一個非常龐大或者複雜的專案中工作時。

1.6.7.2 特性分支

特性分支對任何規模的專案都適用。 特性分支是一種短期分支,它被用來實現單一特性或其相關工作。 也許你從來沒有在其他的版本控制系統(VCS)上這麼做過,因為在那些版本控制系統中建立和合並分支通常很費勁。 然而,在 Git 中一天之內多次建立、使用、合併、刪除分支都很常見。

我們已經在上一節中你建立的 iss53 和 hotfix 特性分支中看到過這種用法。 你在上一節用到的特性分支(iss53 和 hotfix 分支)中提交了一些更新,並且在它們合併入主幹分支之後,你又刪除了它們。 這項技術能使你快速並且完整地進行上下文切換(context-switch)——因為你的工作被分散到不同的流水線中,在不同的流水線中每個分支都僅與其目標特性相關,因此,在做程式碼審查之類的工作的時候就能更加容易地看出你做了哪些改動。 你可以把做出的改動在特性分支中保留幾分鐘、幾天甚至幾個月,等它們成熟之後再合併,而不用在乎它們建立的順序或工作進度。

考慮這樣一個例子,你在 master 分支上工作到 C1,這時為了解決一個問題而新建 iss91 分支,在 iss91 分支上工作到 C4,然而對於那個問題你又有了新的想法,於是你再新建一個 iss91v2 分支試圖用另一種方法解決那個問題,接著你回到 master 分支工作了一會兒,你又冒出了一個不太確定的想法,你便在 C10 的時候新建一個 dumbidea 分支,並在上面做些實驗。 你的提交歷史看起來像下面這個樣子:

Figure 1-20. 擁有多個特性分支的提交歷史

現在,我們假設兩件事情:你決定使用第二個方案來解決那個問題,即使用在 iss91v2 分支中方案;另外,你將 dumbidea 分支拿給你的同事看過之後,結果發現這是個驚人之舉。 這時你可以拋棄 iss91 分支(即丟棄 C5 和 C6 提交),然後把另外兩個分支合併入主幹分支。 最終你的提交歷史看起來像下面這個樣子:

Figure 1-21. 合併了 dumbidea 和 iss91v2 分支之後的提交歷史

1.6.8 遠端分支

1.6.8.1 遠端分支

遠端引用是對遠端倉庫的引用(指標),包括分支、標籤等等。 你可以通過 git ls-remote (remote) 來顯式地獲得遠端引用的完整列表,或者通過 git remote show (remote) 獲得遠端分支的更多資訊。 然而,一個更常見的做法是利用遠端跟蹤分支。

遠端跟蹤分支是遠端分支狀態的引用。 它們是你不能移動的本地引用,當你做任何網路通訊操作時,它們會自動移動。 遠端跟蹤分支像是你上次連線到遠端倉庫時,那些分支所處狀態的書籤。

它們以 (remote)/(branch) 形式命名。 例如,如果你想要看你最後一次與遠端倉庫 origin 通訊時 master 分支的狀態,你可以檢視 origin/master 分支。 你與同事合作解決一個問題並且他們推送了一個 iss53 分支,你可能有自己的本地 iss53 分支;但是在伺服器上的分支會指向 origin/iss53 的提交。

這可能有一點兒難以理解,讓我們來看一個例子。 假設你的網路裡有一個在 git.ourcompany.com 的 Git 伺服器。 如果你從這裡克隆,Git 的 clone 命令會為你自動將其命名為 origin,拉取它的所有資料,建立一個指向它的 master 分支的指標,並且在本地將其命名為 origin/master。 Git 也會給你一個與 origin 的 master 分支在指向同一個地方的本地 master 分支,這樣你就有工作的基礎。

Figure 1-22. 克隆之後的伺服器與本地倉庫

如果你在本地的 master 分支做了一些工作,然而在同一時間,其他人推送提交到 git.ourcompany.com 並更新了它的 master 分支,那麼你的提交歷史將向不同的方向前進。 也許,只要你不與 origin 伺服器連線,你的 origin/master 指標就不會移動。

Figure 1-23. 本地與遠端的工作可以分叉

 

如果要同步你的工作,執行 git fetch origin 命令。 這個命令查詢 “origin” 是哪一個伺服器(在本例中,它是 git.ourcompany.com),從中抓取本地沒有的資料,並且更新本地資料庫,移動 origin/master 指標指向新的、更新後的位置。

Figure 1-24. git fetch 更新你的遠端倉庫引用

1.6.8.2 推送

當你想要公開分享一個分支時,需要將其推送到有寫入許可權的遠端倉庫上。 本地的分支並不會自動與遠端倉庫同步 - 你必須顯式地推送想要分享的分支。 這樣,你就可以把不願意分享的內容放到私人分支上,而將需要和別人協作的內容推送到公開分支。

如果希望和別人一起在名為 serverfix 的分支上工作,你可以像推送第一個分支那樣推送它。 執行 git push (remote) (branch):

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

也可以執行 git push origin serverfix:serverfix,它會做同樣的事 - 相當於它說,“推送本地的 serverfix 分支,將其作為遠端倉庫的 serverfix 分支” 可以通過這種格式來推送本地分支到一個命名不相同的遠端分支。 如果並不想讓遠端倉庫上的分支叫做 serverfix,可以執行 git push origin serverfix:awesomebranch 來將本地的 serverfix 分支推送到遠端倉庫上的 awesomebranch 分支。

下一次其他協作者從伺服器上抓取資料時,他們會在本地生成一個遠端分支 origin/serverfix,指向伺服器的 serverfix 分支的引用:

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

要特別注意的一點是當抓取到新的遠端跟蹤分支時,本地不會自動生成一份可編輯的副本(拷貝)。 換一句話說,這種情況下,不會有一個新的 serverfix 分支 - 只有一個不可以修改的 origin/serverfix 指標。

可以執行 git merge origin/serverfix 將這些工作合併到當前所在的分支。 如果想要在自己的 serverfix 分支上工作,可以將其建立在遠端跟蹤分支之上:

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

這會給你一個用於工作的本地分支,並且起點位於 origin/serverfix

1.6.8.3 跟蹤分支

從一個遠端跟蹤分支檢出一個本地分支會自動建立一個叫做 “跟蹤分支”(有時候也叫做 “上游分支”)。 跟蹤分支是與遠端分支有直接關係的本地分支。 如果在一個跟蹤分支上輸入 git pull,Git 能自動地識別去哪個伺服器上抓取、合併到哪個分支。

當克隆一個倉庫時,它通常會自動地建立一個跟蹤 origin/master 的 master 分支。 然而,如果你願意的話可以設定其他的跟蹤分支 - 其他遠端倉庫上的跟蹤分支,或者不跟蹤 master 分支。 最簡單的就是之前看到的例子,執行 git checkout -b [branch] [remotename]/[branch]。 這是一個十分常用的操作所以 Git 提供了 --track 快捷方式:

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

如果想要將本地分支與遠端分支設定為不同名字,你可以輕鬆地增加一個不同名字的本地分支的上一個命令:

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

現在,本地分支 sf 會自動從 origin/serverfix 拉取。

如果想要檢視設定的所有跟蹤分支,可以使用 git branch 的 -vv 選項。 這會將所有的本地分支列出來並且包含更多的資訊,如每一個分支正在跟蹤哪個遠端分支與本地分支是否是領先、落後或是都有。

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
  master    1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
  testing   5ea463a trying something new

這裡可以看到 iss53 分支正在跟蹤 origin/iss53 並且 “ahead” 是 2,意味著本地有兩個提交還沒有推送到伺服器上。 也能看到 master 分支正在跟蹤 origin/master 分支並且是最新的。 接下來可以看到 serverfix 分支正在跟蹤 teamone 伺服器上的 server-fix-good 分支並且領先 2 落後 1,意味著伺服器上有一次提交還沒有合併入同時本地有三次提交還沒有推送。 最後看到 testing 分支並沒有跟蹤任何遠端分支。

需要重點注意的一點是這些數字的值來自於你從每個伺服器上最後一次抓取的資料。 這個命令並沒有連線伺服器,它只會告訴你關於本地快取的伺服器資料。 如果想要統計最新的領先與落後數字,需要在執行此命令前抓取所有的遠端倉庫。 可以像這樣做:$ git fetch --all; git branch -vv

1.6.8.4 拉取

當 git fetch 命令從伺服器上抓取本地沒有的資料時,它並不會修改工作目錄中的內容。 它只會獲取資料然後讓你自己合併。 然而,有一個命令叫作 git pull 在大多數情況下它的含義是一個 git fetch 緊接著一個 git merge 命令。 如果有一個像之前章節中演示的設定好的跟蹤分支,不管它是顯式地設定還是通過 clone 或 checkout 命令為你建立的,git pull 都會查詢當前分支所跟蹤的伺服器與分支,從伺服器上抓取資料然後嘗試合併入那個遠端分支。

由於 git pull 的魔法經常令人困惑所以通常單獨顯式地使用 fetch 與 merge 命令會更好一些。

1.6.8.5 刪除遠端分支

假設你已經通過遠端分支做完所有的工作了 - 也就是說你和你的協作者已經完成了一個特性並且將其合併到了遠端倉庫的 master 分支(或任何其他穩定程式碼分支)。 可以執行帶有 --delete 選項的 git push 命令來刪除一個遠端分支。 如果想要從伺服器上刪除 serverfix 分支,執行下面的命令:

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

基本上這個命令做的只是從伺服器上移除這個指標。 Git 伺服器通常會保留資料一段時間直到垃圾回收執行,所以如果不小心刪除掉了,通常是很容易恢復的。

 

2、Git的安裝

2.1 Git伺服器端安裝和配置

1)GitLab伺服器端已經在公司伺服器安裝好,訪問地址如下:

http://192.168.1.212:10080/

2)目前已經為技術中心_開發部的同事建立了訪問賬號

3)目前在伺服器端已建立了專案:ypt,並把開發部的同事加入到該專案

訪問地址:http://192.168.1.212:10080/root/ypt.git

2.2 Git客戶端安裝:

1)安裝msysgit(Git客戶端-命令列介面)

下載地址:http://msysgit.github.io/

根據自己作業系統版本情況下載合適的客戶端版本,我這裡有下載好的windows 64位作業系統的客戶端版本,需要的聯絡我

2)安裝TortoiseGit(圖形操作介面)和中文補丁包

我這裡有下載好的安裝程式,有需要的聯絡我

 

3、Git客戶端設定

3.1 訪問賬號設定

1)訪問Git命令列客戶端:

在安裝好的程式組裡選擇Git-àgit Bash即可訪問git命令列工具,如下圖:

3.2設定使用者名稱和電子郵箱

個人的使用者名稱和電子郵件地址很重要,每次git提交時都會引用這兩條資訊,說明是誰提交了更新,所以會隨更新內容一起被永久納入歷史記錄

在Git Bash視窗輸入一下命令設定你的使用者名稱和電子郵箱地址:

git config –global user.name “zhangyi”

git config –global user.email [email protected]

 

檢視已有的配置資訊:

Git config –list

 

3.3設定賬戶的SSH key:

Git使用SSH加密傳輸更新提交資料,確保每次的更新提交不被非法篡改

1)在git bash視窗輸入以下命令,並輸入3個回車:

ssh-keygen -t rsa -C “[email protected]
記得把郵箱換成自己的

 2)開啟“Git GUI”(Git安裝後的另一部分),點選選單的help-ssh,然後copy當前的“key”

 

3)用自己賬號登入Git服務端,點選“profile setting”:

4)在“ssh key”標籤頁把剛生成的公鑰貼上過來並生稱自己的sshkey:

3.4 生成本地金鑰檔案

在Windows開始選單中點“TortoiseGit”程式組,然後選擇“puTTY gen”,如下圖:

在“key generator“視窗生成並儲存金鑰檔案,如下圖:

 

 

 

3.5訪問Git 命令列工具

Git系統可以通過命令列工具來訪問,也可以通過GUI工具來訪問,本文主要介紹命令列工具

1)選擇或建立一個工作目錄

2)在該目錄點選滑鼠右鍵,在彈出選單中選擇”Git Bash Here”選單項

Git會開啟Bash命令列視窗,並把當前目錄設定為你的工作目錄

 

4、Git操作演示

4.1從當前目錄初始化

1)  要對現有的某個專案開始用Git進行管理,只需要在此專案所在的目錄執行命令 Git init

初始化後,在當前目錄下會出現一個名為.git的隱藏子目錄,所有Git需要的資料和資源都存放在這個目錄中。

1)  使用 git add 命令把當前目錄下的檔案加入版本控制:

git add *  把全部檔案和目錄加入版本控制

4)  使用git status 檢視檔案的狀態

 

 

2)  使用git commit命令提交本地版本庫:

git commit –m “initial project version”

或者使用GUI提交:滑鼠右鍵單擊專案目錄,在彈出選單中選”Git提交”

在提交介面中填寫日誌資訊,設定提交日期和作者資訊,然後點選確定即可,如下圖

 

提交後,檔案目錄圖示發生改變,如下圖:

4.2 從現有倉庫克隆

如果想把已有專案的git倉庫複製一份出來,需要用到Git clone命令

Git clone http://localhost:10080/root/ypt.git

或者使用GUI來操作

滑鼠右鍵你的工作目錄,在彈出選單中選擇“Git克隆”即可

 

4.3 推送本地庫到伺服器

在把專案檔案提交到本地版本庫後,就可以吧本地庫推送到伺服器

用滑鼠右鍵點選專案目錄,在彈出選單中選“推送”,如下圖:

 

在彈出視窗選擇“管理”,如下圖:

在彈出視窗中填寫遠端伺服器Git專案的訪問地址,如下圖:

專案地址為:http://192.168.1.212:10080/root/ypt.git

關閉“管理”視窗,在“推送”視窗選擇剛設定的“ypt”遠端伺服器進行推送

相關推薦

版本控制工具git之生成ppk及使用

一、簡介 Git是一款免費、開源的分散式版本控制系統,用於敏捷高效地處理任何或小或大的專案。 Git是一個開源的分散式版本控制系統,用以有效、高速的處理從很小到非常大的專案版本管理。 Git 是 Linus Torvalds 為了幫助管理 Linux 核心開發而開發的一個開放原始碼

分散式版本控制工具Git

一、Git技術簡介 Git是一個分散式版本控制系統,與集中式的SVN不同。     1. 主要特點 集中式特點: 所有人的資源全部儲存在中央伺服器。 所有人開發前都需要從中央伺服器上下載同步其他人的程式碼才能繼續開發,慢。 中央伺服器一旦資料丟失,意味著所有資料全

分布式版本控制工具Git

版本庫 dex cells -m 本質 版本號 機制 win 所有 一、Git技術簡介 Git是一個分布式版本控制系統,與集中式的SVN不同。 1. 主要特點 集中式特點: 所有人的資源全部保存在中央服務器。 所有人開發前都需要從中央服務器上下載同

版本控制工具Git的基本使用

學無止境,精益求精! 十年河東,十年河西,莫欺少年窮! 學歷代表你的過去,能力代表你的現在,學習代表你的將來! 本篇部落格是轉發的別人的,原文地址:http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html

[軟體]如何使用分散式版本控制工具Git

Git是一個由林納斯·託瓦茲為了更好地管理linux核心開發而創立的分散式版本控制/軟體配置管理軟體。需要注意的是和GNU Interactive Tools,一個類似Norton Commander介面的檔案管理器相區分。Git最初的開發動力來自於BitKeeper和Monotone[2][3]。Git最初

版本控制工具: git (程式碼上傳,下載)

如何使用git 命令列 idea中使用git圖形化外掛 part1:  git 歷史簡介 什麼是git  ?                    由linux社群開發的,  一種分散式的,  版本控制系統 什麼是版本控制系統 ?    一種記錄一個或若干檔案內容變化,

【學習筆記】版本控制工具 GIT

前言 GIT是一個分散式的版本控制工具。 參考資料 git官方教程-中文版 及 廖雪峰老師的git教程 下文面向windows系統,所有操作使用git自帶的git bash。 編輯文字文件時不要使用記事本,可以用sublime text或notepad++.

專案版本控制工具----Git

版本控制的工具我早之前用的svn,後來換成了git。同樣是版本控制,為什麼要換呢?肯定是有原因的啦~   一、Git和SVN的比較  svn的優缺點 優點: 1.管理方便,邏輯明確,符合一般人思維習慣。 2.易於管理,集中式伺服器更能保證安全性。 3.程式碼一致性非常高,適合

版本控制工具 git與svn(分散式vs集中式)

版本控制:即記錄一個或若干檔案內容變化,以便將來查閱特定版本修訂情況以及回溯的系統。 集中式–svn SVN, 全名Subvision; 作為集中式版本控制工具,版本庫集中存放在中央伺服器,team裡每個人work時從中央伺服器下載程式碼,是必須聯網才能工作

敏捷開發技術之版本控制工具GIT

GIT是一款免費的,開源的,分散式的程式碼管理工具。原來是在linux系統執行的,對windows整合不是很好, 經過不斷髮展,windows版本也支援了,原來都是用SVN,ClearCase,現在轉入GIT看看,有什麼不同吧! 先安裝Git_V1.9.5_preview針

版本控制工具Git

1、 版本控制基礎 1.1什麼是版本控制工具git? 1) Git是一個開源的分散式版本控制系統。 2)與SVN,CVS相比, Git不需要中心倉庫 3)Git的分支與合併比較簡單,版本對比快 4)GitHub是一個基於web與Git的一個專案託管服務平臺,要

【web前端自動化工作環境配置】6. 版本控制工具git與githup的區別與聯絡以及git的基本用法

  最近專案裡面在用Git提交程式碼,剛開始的時候對這個工具也不是很瞭解,業餘時間抽空就學習了一下。Git是一個原始碼管理工具,便於大家協同開發,在一個專案中,凡是由開發人員編寫的程式碼都是原始碼,都需要被管理起來,讓原始碼容易被追溯,主要記錄每次變更了什麼,誰主導了這次的變

版本控制工具——Git常用操作(下)

之前 將在 根據 並且 fsck args git工作區 with 索引 本文由雲+社區發表 作者:工程師小熊 摘要:上一集我們一起入門學習了git的基本概念和git常用的操作,包括提交和同步代碼、使用分支、出現代碼沖突的解決辦法、緊急保存現場和恢復現場的操作。學會

基於GitLab與Git Extensions搭建版本控制工具

基本 cmd img html nat 需求 無法 spa hang 1.背景   大家知道GitHub是現在非常流行的代碼托管工具,但是如果有些項目不想開源的話,則需要付費,因此萌生了自己搭建一個Git的版本控制工具,供內網使用。GitLab則是個好的選擇,但是GitL

Git分布式版本控制工具

繼續 新建 執行 是把 -h png 版本號 工作 直接 一、安裝Git    1、下載Windows版的Git:msysgit;官方下載地址:http://msysgit.github.io,安裝選定要安裝的目錄(路徑杜絕中文),剩下的按照默認安裝即可,參考:GIt安裝教

版本控制工具Git

但是 不想 之前 設置 xxx 遠程 -o span 兩種 git三層結構 工作區working directory 暫存區staging index 版本庫git directory(Repository) Git文件的四種狀態 untracked未被追蹤 Modifie

版本控制工具Svn及Git

例如 ech source -s lan https git add 更改 date 首先介紹svn,屬於老牌的工具 svn ci 提交代碼 alias commit svn up 更新代碼 alias update svn st 修改的文件 alias st svn di

1.git版本控制工具的安裝與使用

use ssh-key origin read name log -- cache 本地倉庫 git下載 官方地址:https://git-scm.com/download/win 百度雲地址:我的網盤/安裝文件/Git-2.15.0-64-bit.rar git基本使

git版本控制工具的使用

如果 pre git log 包括 load tps 出現 怎麽 ini 目錄 git版本管理工具使用 一丶Git的下載與安裝 1.windows下的git的下載與安裝 2.linux下的git安裝 二丶常用命令 三丶Git倉庫 1.配置倉庫信息 2.倉庫的創建於管理

關於git版本控制工具的操作命令

一.安裝git,首先去git官網下載git,https://git-scm.com/downloads,下載.exe格式並安裝   二.git生成金鑰: (1) ssh-keygen -t rsa -C "[email protected]",-------