標籤:

Git 初學者教程

Git 初學者教程

一共分為三個部分,可挑選想看內容:

一、Git基礎

二、Git分支

三、Git遠程操作

一、Git基礎

1.1 記錄快照

Git 保存數據是對文件系統的一組快照。 每次你提交更新時,它主要對當時的全部文件製作一個快照。如果文件沒有修改,Git 只保留一個鏈接指向之前存儲的文件。

1.2 三個工作區域

Git 有三個區域:工作目錄(Working Directory),暫存目錄(Stage or Index),倉庫(Git directory)。 基本的 Git 工作流程如下:

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

工作目錄就是你正在耕耘的項目文件夾,當你向暫存目錄提交時,會以快照的形式被存放其中。提交後若修改了工作目錄中的文件,再次提交會生成新的快照覆蓋到暫存目錄。

倉庫,是 Git 中最重要的部分,由圖中綠色塊組成,數據結構看起來像一個單向鏈表,但後面會提到其實是樹。每一個節點都是印有哈希值的快照組,也就是項目的一個版本。倉庫中有一個或多個指針,代表分支,指向某一個節點。只有一個 HEAD 指針指向正在工作的分支。

當你從暫存目錄向倉庫提交時,Git 用暫存區域的文件創建一個新的提交,並把此時的節點設為父節點。然後把當前分支指向新的提交節點。下一圖中,當前分支是master。 在運行命令之前,master指向ed489,提交後,master指向新的節點f0cec並以ed489作為父節點。下二圖中,在master分支的祖父節點maint分支進行一次提交,生成了1800b。

1.3 基本用法

上面的四條命令在工作目錄、暫存目錄(也叫做索引)和倉庫之間複製文件。

  • git add files 把當前文件放入暫存區域。
  • git commit 給暫存區域生成快照並提交。
  • git reset -- files 用來撤銷最後一次git add files,你也可以用git reset撤銷所有暫存區域文件。
  • git checkout -- files 把文件從暫存區域複製到工作目錄,用來丟棄本地修改。

你可以用 git reset -p, git checkout -p, or git add -p進入交互模式。

也可以跳過暫存區域直接從倉庫取出文件或者直接提交代碼。

  • git commit -a 相當於運行 git add 把所有當前目錄下的文件加入暫存區域再運行。
  • git commit files 進行一次包含最後一次提交加上工作目錄中文件快照的提交。並且文件被添加到暫存區域。
  • git checkout HEAD -- files 回滾到複製最後一次提交。

diff

checkout

checkout命令用於從歷史提交(或者暫存區域)中拷貝文件到工作目錄,也可用於切換分支。

當給定某個文件名(或者打開-p選項,或者文件名和-p選項同時打開)時,git會從指定的提交中拷貝文件到暫存區域和工作目錄。比如,git checkout HEAD~ foo.c會將提交節點HEAD~(即當前提交節點的父節點)中的foo.c複製到工作目錄並且加到暫存區域中。(如果命令中沒有指定提交節點,則會從暫存區域中拷貝內容。)注意當前分支不會發生變化。

當不指定文件名,而是給出一個(本地)分支時,那麼HEAD標識會移動到那個分支(也就是說,我們「切換」到那個分支了),然後暫存區域和工作目錄中的內容會和HEAD對應的提交節點一致。新提交節點(下圖中的a47c3)中的所有文件都會被複制(到暫存區域和工作目錄中);只存在於老的提交節點(ed489)中的文件會被刪除;不屬於上述兩者的文件會被忽略,不受影響。

該做法盡量避免。如果既沒有指定文件名,也沒有指定分支名,而是一個標籤、遠程分支、SHA-1值或者是像master~3類似的東西,就得到一個匿名分支,稱作detached HEAD(被分離的HEAD標識)。這樣可以很方便地在歷史版本之間互相切換。比如說你想要編譯1.6.6.1版本的git,你可以運行git checkout v1.6.6.1(這是一個標籤,而非分支名),編譯,安裝,然後切換回另一個分支,比如說git checkout master。

二、Git分支

2.1 創建分支

創建分支其實就是創建了一個新的指針。使用的指令是git branch

$ git branch testing

這會在當前所在的提交對象上創建一個testing指針, 但是此時HEAD指針仍然指向原分支,所以準備在testing分支上工作前,需要切換分支。

2.2 切換分支

需要使用的指令是git checkout:

$ git checkout testing

這樣HEAD就指向testing分支了,此時提交代碼將會和master分離,產生分叉。

當然,需要將HEAD切換回master才能在master分支上提交。

以上兩條命令可以合併成一句,用一個帶有-b參數的git checkout命令:

git checkout -b testing

2.4 合併分支

是時候將分支的代碼整合起來,需要用git merge命令合併分支。首先確定需要併入到哪一條分支,通常情況下會需要併入到master,所以先將HEAD切換到master:

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

Git 將此次合併的結果做了一個新的快照並且讓master指向它。這裡有一個特殊情況就是當master所指的快照是分支的父節點,那麼merge操作將會直接移動master指針到分支指針的位置。

如果沒有任何衝突,那麼合併到這裡就結束了。但大部分情況,代碼往往不能簡單的自動合併,比如兩個分支均修改了同一個變數。任何因包含合併衝突而有待解決的文件,都會以未合併狀態標識出來。Git 會在有衝突的文件中加入標準的衝突解決標記,這樣你可以打開這些包含衝突的文件然後手動解決衝突。出現衝突的文件會包含一些特殊區段,看起來像下面這個樣子:

<<<<<<< HEAD:index.html<div id="footer">contact : email.support@github.com</div>=======<div id="footer"> please contact us at support@github.com</div>>>>>>>> iss53:index.html

此時只需要妥善處理衝突,確保已經把 <<<<<<< , ======= , 和 >>>>>>> 這些行完全刪除。在解決了所有文件里的衝突之後,對每個文件使用 git add 命令來將其標記為衝突已解決。一旦暫存這些原本有衝突的文件,Git 就會將它們標記為衝突已解決。

這就是 Git 分支的基本操作,工作中使用往往需要一定的管理策略,可以參考阮一峰的 Git分支管理策略

三、Git遠程操作

遠程操作僅僅多出一個工作區域,即遠程倉庫(Remote)。詳見下圖:

git remote

一個本地倉庫可以和多個遠程倉庫交流。為了便於管理,Git要求每個遠程主機都必須指定一個主機名。git remote就用於管理主機名。 不帶選項的時候,git remote命令列出所有遠程主機。

$ git remote origin

使用-v選項,可以參看遠程主機的網址。

$ git remote -v origin git@github.com:jquery/jquery.git (fetch) origin git@github.com:jquery/jquery.git (push)

上面命令表示,當前只有一台遠程主機,叫做origin,以及它的網址。

克隆版本庫的時候,所使用的遠程主機自動被Git命名為origin。如果想用其他的主機名,需要用git clone命令的-o選項指定。

$ git clone -o jQuery https://github.com/jquery/jquery.git$ git remote jQuery

面命令表示,克隆的時候,指定遠程主機叫做jQuery。

git remote show命令加上主機名,可以查看該主機的詳細信息。

$ git remote show <主機名>

git remote add命令用於添加遠程主機。

$ git remote add <主機名> <網址>

git remote rm命令用於刪除遠程主機。

$ git remote rm <主機名>

git remote rename命令用於遠程主機的改名。

$ git remote rename <原主機名> <新主機名>

取回代碼

Git的遠程操作基本上就是兩類:取回代碼和上傳代碼。

git clone

如果新建了一個空白的本地倉庫,通常要克隆遠程倉庫到本地,這時就要用到git clone命令。

$ git clone <版本庫的網址>

比如,克隆jQuery的版本庫。

$ git clone https://github.com/jquery/jquery.git

該命令會在本地主機生成一個目錄,與遠程主機的版本庫同名。如果要指定不同的目錄名,可以將目錄名作為git clone命令的第二個參數。

$ git clone <版本庫的網址> <本地目錄名>

git clone支持多種協議,除了HTTP(s)以外,還支持SSH、Git、本地文件協議等,下面是一些例子。

$ git clone http[s]://example.com/path/to/repo.git/$ git clone ssh://example.com/path/to/repo.git/$ git clone git://example.com/path/to/repo.git/$ git clone /opt/git/project.git $ git clone file:///opt/git/project.git$ git clone ftp[s]://example.com/path/to/repo.git/$ git clone rsync://example.com/path/to/repo.git/

SSH協議還有另一種寫法。

$ git clone [user@]example.com:path/to/repo.git/

通常來說,Git協議下載速度最快,SSH協議用於需要用戶認證的場合。各種協議優劣的詳細討論請參考官方文檔

git fetch

當遠程倉庫有更新需要取回本地時,就要用到git fetch命令。

$ git fetch <遠程主機名>

上面命令將某個遠程主機的更新,全部取回本地。默認情況下,git fetch取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。

$ git fetch <遠程主機名> <分支名>

比如,取回origin主機的master分支。

$ git fetch origin master

所取回的更新,在本地主機上要用」遠程主機名/分支名」的形式讀取。比如origin主機的master,就要用origin/master讀取。

git branch命令的-r選項,可以用來查看遠程分支,-a選項查看所有分支。

$ git branch -rorigin/master$ git branch -a* master remotes/origin/master

上面命令表示,本地主機的當前分支是master,遠程分支是origin/master。

取回遠程主機的更新以後,可以在它的基礎上,使用git checkout命令創建一個新的分支。

$ git checkout -b newBrach origin/master

上面命令表示,在origin/master的基礎上,創建一個新分支。

此外,也可以使用git merge命令或者git rebase命令,在本地分支上合併遠程分支。

$ git merge origin/master# 或者$ git rebase origin/master

上面命令表示在當前分支上,合併origin/master。

git pull

git pull命令的作用是,取回遠程主機某個分支的更新,再與本地的指定分支合併。

$ git pull <遠程主機名> <遠程分支名>:<本地分支名>

實質上,這等同於先做git fetch,再做git merge

$ git fetch origin$ git merge origin/next

在某些場合,Git會自動在本地分支與遠程分支之間,建立一種追蹤關係(tracking)。比如,在git clone的時候,所有本地分支默認與遠程主機的同名分支,建立追蹤關係,也就是說,本地的master分支自動」追蹤」origin/master分支。

Git也允許手動建立追蹤關係。

git branch --set-upstream master origin/next

上面命令指定master分支追蹤origin/next分支。

如果當前分支與遠程分支存在追蹤關係,git pull就可以省略遠程分支名。

$ git pull origin

上面命令表示,本地的當前分支自動與對應的origin主機」追蹤分支」(remote-tracking branch)進行合併。

如果當前分支只有一個追蹤分支,連遠程主機名都可以省略,當前分支自動與唯一一個追蹤分支進行合併。

$ git pull

如果合併需要採用rebase模式,可以使用–rebase選項。

$ git pull --rebase <遠程主機名> <遠程分支名>:<本地分支名>

上傳代碼

上傳之前,為了防止遠程倉庫代碼庫發生衝突,一般都需要先git pull,以確保上傳代碼沒有過舊。

git push

git push命令用於將本地分支的更新,推送到遠程主機。它的格式與git pull命令相仿。

$ git push <遠程主機名> <本地分支名>:<遠程分支名>

如果當前分支與遠程分支之間存在追蹤關係,則本地分支和遠程分支都可以省略。

$ git push origin

上面命令表示,將當前分支推送到origin主機的對應分支。

如果當前分支只有一個追蹤分支,那麼主機名都可以省略。

$ git push

如果當前分支與多個主機存在追蹤關係,則可以使用-u選項指定一個默認主機,這樣後面就可以不加任何參數使用git push

$ git push -u origin master

迄今,Git初學者系列結束了。該系列僅僅介紹日常工作學習中需要的 Git 操作,如果有更高的需求或其他疑問,請參見 Pro Git

本文參考博客:LiaoHanfus。


推薦閱讀:

Git的基礎使用教程
GitHub &amp; Bitbucket &amp; GitLab &amp; Coding 的對比分析
Github上都有哪些有用但不為大家熟知的小功能?
Git Tips #1:不再輸錯 git 命令
git bash在輸入git commit -m的時候忘記輸入信息,卡在一個頁面無法退出怎麼解決?

TAG:教程 | Git |