讀Git Pro2的筆記

什麼是Git

基礎概念

三個工做區域:git

    1. Git 倉庫 : Git 用來保存項目的元數據和對象數據庫的地方。這是 Git 中最重要的部分,從其它計算機克隆倉庫時,拷貝的就是這裏的數據;
    1. 工做目錄 : 對項目的某個版本獨立提取出來的內容。這些從 Git 倉庫的壓縮數據庫中提取出來的文件,放在磁盤上供你使用或修改;
    1. 暫存區域 : 一個文件,保存了下次將提交的文件列表信息,通常在 Git 倉庫目錄中。有時候也被稱做`‘索引’',不過通常說法仍是叫暫存區域。

git 中文件的狀態:github

    1. 未追蹤(untracked):
    1. 已追蹤(tracked) :追蹤的文件分下面3中狀態
      1. 已提交(committed):已提交表示數據已經安全的保存在本地數據庫中;
      1. 已修改(modified) :已修改表示修改了文件,但還沒保存到數據庫中;
      1. 已暫存(staged) :已暫存表示對一個已修改文件的當前版本作了標記,使之包含在下次提交的快照中。

三個配置文件:正則表達式

    1. /etc/gitconfig 文件: 包含系統上每個用戶及他們倉庫的通用配置。 若是使用帶有 --system 選項的 git config 時,它會今後文件讀寫配置變量。
    1. ~/.gitconfig 或 ~/.config/git/config 文件:只針對當前用戶。 能夠傳遞 --global 選項讓 Git 讀寫此文件。
    1. 當前使用倉庫的 Git 目錄中的 config 文件(就是 .git/config):針對該倉庫。

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

命令:

配置信息

git config --list : 檢查當前應用的配置信息
    git config <key>  :來檢查 Git 的某一項配置

獲取幫助

$ git help <verb>
    $ git <verb> --help
    $ man git-<verb>

Git 基礎

在學習完本章以後,你應該可以配置並初始化一個倉庫(repository)、開始或中止跟蹤 (track)文件、暫存(stage)或提交(commit)更改。本章也將向你演示如何配置 Git 來忽略指定的文件和文 件模式、如何迅速而簡單地撤銷錯誤操做、如何瀏覽你的項目的歷史版本以及不一樣提交(commits)間的差別、 如何向你的遠程倉庫推送(push)以及如何從你的遠程倉庫拉取(pull)文件。shell

命令

獲取 Git 倉庫

git init #該命令將建立一個名爲 .git 的子目錄,這個子目錄含有你初始化的 Git 倉庫中全部的必須文件,
             #這些文件是Git倉庫的骨幹。可是,在這個時候,咱們僅僅是作了一個初始化的操做,你的項目裏的文件尚未被跟蹤。

克隆現有的倉庫

git clone [url] # 當你執行 git clone 命令的時候,默認配置下遠程 Git 倉庫中的每個文件的每個版本都將被拉取下來。

好比,要克隆 Git 的可連接庫 libgit2,能夠用下面的命令:數據庫

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

說明:這會在當前目錄下建立一個名爲 「libgit2」 的目錄,並在這個目錄下初始化一個 .git 文件夾,從遠程倉庫拉 取下全部數據放入 .git 文件夾,而後從中讀取最新版本的文件的拷貝。vim

Git 支持多種數據傳輸協議。上面的例子使用的是 https:// 協議,不過你也可使用 git:// 協議或者使用 SSH 傳輸協議,好比 user@server:path/to/repo.git 。安全

工做目錄下的每個文件都不外乎這兩種狀態: 已跟蹤 :已跟蹤的文件是指那些被歸入了版本控制的文件,在上一次快照中有它們的記錄,在工做一段時間後,它們的狀態可能處於未修改,已修改或已放 入暫存區。 未跟蹤 :工做目錄中除已跟蹤文件之外的全部其它文件都屬於未跟蹤文件,它們既不存在於上次快照的記錄中,也沒有放入暫存區。初次克隆某個倉庫的時 候,工做目錄中的全部文件都屬於已跟蹤文件,並處於未修改狀態。服務器

檢查當前文件狀態

git status # 查看哪些文件處於什麼狀態
    git status -s # 狀態簡覽    ==  git status --short

命令結果分析:編輯器

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt
  1. ?? : 新添加的未跟蹤文件;
  2. A : 新添加到暫存區中的文件;
  3. M : 修改過的文件; 出如今右邊的 M 表示該文件被修改了可是還沒放入暫存區,出如今靠左邊的 M 表示該文件被修改了並放入了暫存區
  4. D :

跟蹤新文件

git add <fileName> | <path>  # 使用文件或目錄的路徑做爲參數;若是參數是目錄的路徑,該命令將遞歸地跟蹤該目錄下的全部文件。

忽略文件

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

例如:

$ cat .gitignore
*.[oa]
*~

說明: 第一行告訴 Git 忽略全部以 .o 或 .a 結尾的文件。通常這類對象文件和存檔文件都是編譯過程當中出現的。 第二行告訴 Git 忽略全部以波浪符(~)結尾的文件,許多文本編輯軟件(好比 Emacs)都用這樣的文件名保存副本。 此外,你可能還須要忽略 log,tmp 或者 pid 目錄,以及自動生成的文檔等等。要養成一開始就設置好.gitignore 文件的習慣,以避免未來誤提交這類無用的文件。

文件 .gitignore 的格式規範以下:

  • [x] 1. 全部空行或者以 # 開頭的行都會被 Git 忽略。
  • [x] 2. 可使用標準的 glob 模式匹配。
  • [x] 3. 匹配模式能夠以(/)開頭防止遞歸。
  • [x] 4. 匹配模式能夠以(/)結尾指定目錄。
  • [x] 5. 要忽略指定模式之外的文件或目錄,能夠在模式前加上驚歎號(!)取反。

說明:

glob 模式:指 shell 所使用的簡化了的正則表達式。 星號(*)匹配零個或多個任意字符; [abc] 匹配任何一個列在方括號中的字符(這個例子要麼匹配一個 a,要麼匹配一個 b,要麼匹配一個 c); 問號(?)只匹配一個任意字符; 若是在方括號[]中使用短劃線分隔兩個字符,表示全部在這兩個字符範圍內的均可以匹配(好比[0-9] 表示匹配全部 0 到 9 的數字); 使用兩個星號(*)表示匹配任意中間目錄,好比a/**/z 能夠匹配 a/z,a/b/z 或 a/b/c/z等。

舉個例子:

# no .a files ,忽略.a結尾的文件
*.a
# but do track lib.a, even though you're ignoring .a files above ,在第一個忽略文件中排出lib.a文件
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO,僅僅只忽略當前/TODO目錄下的文件
/TODO
# ignore all files in the build/ directory,忽略build目錄下的全部文件或者文件夾,包括子文件或者文件夾
build/
# ignore doc/notes.txt, but not doc/server/arch.txt,僅僅只忽略當前doc目錄下的文件的後綴爲.txt文件,可是不包括子文件夾下的文件
doc/*.txt
# ignore all .pdf files in the doc/ directory,忽略doc目錄下的全部.pdf後綴文件,包括子文件夾中的後綴爲.pdf的文件
doc/**/*.pdf
TIP

查看已暫存和未暫存的修改

git diff            # 此命令比較的是工做目錄中當前文件和暫存區域快照之間的差別
git diff --staged   # 查看已暫存的將要添加到下次提交裏的內容【暫存區和本分支的repo最後一次的commit的比較】  
git diff --cached   # 這個是git diff --staged 的舊版本的命令,可是git一直向下兼容;

Git Diff 的插件版本 使用 git diff 來分析文件差別。可是,若是你喜歡經過圖形化的方式或其 它格式輸出方式的話,可使用 git difftool 命令來用 Araxis ,emerge 或 vimdiff 等軟 件輸出 diff 分析結果。使用 git difftool --tool-help 命令來看你的系統支持哪些 Git Diff 插件。

提交更新

git commit  # 把暫存區的文件所有提交到repo倉庫中

這種方式會啓動文本編輯器以便輸入本次提交的說明。(默認會啓用 shell 的環境變量 $EDITOR 所指定的軟件, 通常都是 vim 或 emacs。固然也能夠按照 起步 介紹的方式,使用 git config --global core.editor 命 令設定你喜歡的編輯軟件。)

編輯器會顯示相似下面的文本信息(本例選用 Vim 的屏顯方式展現):

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# new file: README
# modified: CONTRIBUTING.md
#~~~
".git/COMMIT_EDITMSG" 9L, 283C

能夠看到,默認的提交消息包含最後一次運行 git status 的輸出,放在註釋行裏,另外開頭還有一空行,供 你輸入提交說明。你徹底能夠去掉這些註釋行,不過留着也不要緊,多少能幫你回想起此次更新的內容有哪些。 (若是想要更詳細的對修改了哪些內容的提示,能夠用 -v 選項,這會將你所作的改變的 diff 輸出放到編輯器中從 而使你知道本次提交具體作了哪些修改。)退出編輯器時,Git 會丟掉註釋行,用你輸入提交附帶信息生成一次 提交。

git commit -m "<message>"  # 提交的信息
[master 463dc4f] Story 182: Fix benchmarks for speed
2 files changed, 2 insertions(+)
create mode 100644 README

能夠看到,提交後它會告訴你,當前是在哪一個分支(master)提交的,本 次提交的完整 SHA-1 校驗和是什麼(463dc4f),以及在本次提交中,有多少文件修訂過,多少行添加和刪改 過。

跳過使用暫存區域

git commit -a -m "<message>" # Git 就會自動把全部已經**跟蹤過的**文件暫存起來一併提交

移除文件

  1. 要從 Git 中移除某個文件,就必需要從已跟蹤文件清單中移除(確切地說,是從暫存區域移除),而後提交。 能夠用 git rm 命令完成此項工做,並連帶從工做目錄中刪除指定的文件,這樣之後就不會出如今未跟蹤文件清單中了。
git rm <fileName>  # 把暫存區和工做目錄中的文件所有刪除,注意這個文件要有commit操做,要否則是要強力刪除的

下一次提交時,該文件就再也不歸入版本管理了。若是刪除以前修改過而且已經放到暫存區域的話,則必需要用強 制刪除選項 -f(譯註:即 force 的首字母)。這是一種安全特性,用於防止誤刪尚未添加到快照的數據,這 樣的數據不能被 Git 恢復。

  1. 另一種狀況是,咱們想把文件從 Git 倉庫中刪除(亦即從暫存區域移除),但仍然但願保留在當前工做目錄 中。換句話說,你想讓文件保留在磁盤,可是並不想讓 Git 繼續跟蹤。當你忘記添加 .gitignore 文件,不小 ? 心把一個很大的日誌文件或一堆 .a 這樣的編譯生成文件添加到暫存區時,這一作法尤爲有用。爲達到這一目 的,使用 --cached 選項:
git rm --cached <fileName> # 只是單純的把文件從暫存區刪除,不刪除工做目錄下的文件

git rm 命令後面能夠列出文件或者目錄的名字,也可使用 glob 模式

例如:

git rm log/\*.log

注意到星號 * 以前的反斜槓 \,由於 Git 有它本身的文件模式擴展匹配方式,因此咱們不用 shell 來幫忙展開。 此命令刪除 log/ 目錄下擴展名爲 .log 的全部文件。

移動文件

不像其它的 VCS 系統,Git 並不顯式跟蹤文件移動操做。若是在 Git 中重命名了某個文件,倉庫中存儲的元數據 並不會體現出這是一次更名操做。不過 Git 很是聰明,它會推斷出究竟發生了什麼,至於具體是如何作到的,我 們稍後再談。

git mv file_from file_to #

它會恰如預期般正常工做。實際上,即使此時查看狀態信息,也會明白無誤地看到關於重命名操做的說明:

$ git mv README.md README
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README

其實,運行 git mv 就至關於運行了下面三條命令:

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

如此分開操做,Git 也會意識到這是一次更名,因此無論何種方式結果都同樣。二者惟一的區別是,mv 是一條命 令而另外一種方式須要三條命令,直接用 git mv 輕便得多。不過有時候用其餘工具批處理更名的話,要記得在提 交前刪除老的文件名,再添加新的文件名。

查看提交歷史

git log # 查看當前分支的日誌
$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit

默認不用任何參數的話: git log 會按提交時間列出全部的更新,最近的更新排在最上面;

  1. 這個命令會列出每一個提交的 SHA-1 校驗;
  2. 做者的名字和電子郵件地址;
  3. 提交時間;
  4. 提交說明;

git log 經常使用參數的介紹:

  1. 一個經常使用的選項是 -p,用來顯示每次提交的內容差別。你也能夠加上 -2 來僅顯示最近兩次提交:
$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "simplegit"
- s.version = "0.1.0"
+ s.version = "0.1.1"
s.author = "Scott Chacon"
s.email = "schacon@gee-mail.com"
s.summary = "A simple gem for using Git in Ruby code."
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
end
end
-
-if $0 == __FILE__
- git = SimpleGit.new
- puts git.show
-end
\ No newline at end of file

該選項除了顯示基本信息以外,還在附帶了每次 commit 的變化。當進行代碼審查,或者快速瀏覽某個搭檔提交 的 commit 所帶來的變化的時候,這個參數就很是有用了。你也能夠爲 git log 附帶一系列的總結性選項。比 如說,若是你想看到每次提交的簡略的統計信息,你可使用 --stat 選項:

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
Rakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test
lib/simplegit.rb | 5 -----
1 file changed, 5 deletions(-)
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
README | 6 ++++++
Rakefile | 23 +++++++++++++++++++++++
lib/simplegit.rb | 25 +++++++++++++++++++++++++
3 files changed, 54 insertions(+)

正如你所看到的,--stat 選項在每次提交的下面列出額全部被修改過的文件、有多少文件被修改了以及被修改 過的文件的哪些行被移除或是添加了。在每次提交的最後還有一個總結。

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

$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit

但最有意思的是 format,能夠定製要顯示的記錄格式。這樣的輸出對後期提取分析格外有用 — 由於你知道 輸出的格式不會隨着Git的更新而發生改變:

$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
git log --pretty=format   #經常使用的選項 列出了經常使用的格式佔位符寫法及其表明的意義。

git log --pretty=format 經常使用的選項

選項 說明
%H 提交對象(commit)的完整哈希字串
%h 提交對象的簡短哈希字串
%T 樹對象(tree)的完整哈希字串
%t 樹對象的簡短哈希字串
%P 父對象(parent)的完整哈希字串
%p 父對象的簡短哈希字串
%an 做者(author)的名字
%ae 做者的電子郵件地址
%ad 做者修訂日期(能夠用 --date= 選項定製格式)
%ar 做者修訂日期,按多久之前的方式顯示
%cn 提交者(committer)的名字
%ce 提交者的電子郵件地址
%cd 提交日期
%cr 提交日期,按多久之前的方式顯示
%s 提交說明

你必定奇怪 做者 和 提交者 之間究竟有何差異,其實做者指的是實際做出修改的人,提交者指的是最後將此工做 成果提交到倉庫的人。因此,當你爲某個項目發佈補丁,而後某個核心成員將你的補丁併入項目時,你就是做 者,而那個核心成員就是提交者。

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

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
* 11d191e Merge branch 'defunkt' into local

這種輸出類型會在咱們下一張學完分支與合併之後變得更加有趣。

git log 的經常使用選項

選項 說明
-p 按補丁格式顯示每一個更新之間的差別。
--stat 顯示每次更新的文件修改統計信息。
--shortstat 只顯示 --stat 中最後的行數修改添加移除統計。
--name-only 僅在提交信息後顯示已修改的文件清單。
--name-status 顯示新增、修改、刪除的文件清單。
--abbrev-commit 僅顯示 SHA-1 的前幾個字符,而非全部的 40 個字符。
--relative-date 使用較短的相對時間顯示(好比,「2 weeks ago」)。
--graph 顯示 ASCII 圖形表示的分支合併歷史。
--pretty 使用其餘格式顯示歷史提交信息。可用的選項包括 oneline,short,full,fuller 和format(後跟指定格式)。

限制輸出長度

除了定製輸出格式的選項以外,git log 還有許多很是實用的限制輸出長度的選項,也就是隻輸出部分提交信 息。以前你已經看到過 -2 了,它只顯示最近的兩條提交,實際上,這是 -<n> 選項的寫法,其中的 n 能夠是任 何整數,表示僅顯示最近的若干條提交。不過實踐中咱們是不太用這個選項的,Git 在輸出全部提交時會自動調 用分頁程序,因此你一次只會看到一頁的內容。

另外還有按照時間做限制的選項,好比 --since 和 --until 也頗有用。例如,下面的命令列出全部最近兩週 內的提交:

$ git log --since=2.weeks

這個命令能夠在多種格式下工做,好比說具體的某一天 "2008-01-15",或者是相對地多久之前 "2 years 1 day 3 minutes ago"。

還能夠給出若干搜索條件,列出符合的提交。用 --author 選項顯示指定做者的提交,用 --grep 選項搜索提 交說明中的關鍵字。(請注意,若是要獲得同時知足這兩個選項搜索條件的提交,就必須用 --all-match 選 項。不然,知足任意一個條件的提交都會被匹配出來) 另外一個很是有用的篩選選項是 -S,能夠列出那些添加或移除了某些字符串的提交。好比說,你想找出添加或移 除了某一個特定函數的引用的提交,你能夠這樣使用:

$ git log -Sfunction_name

最後一個很實用的 git log 選項是路徑(path),若是隻關心某些文件或者目錄的歷史提交,能夠在 git log 選項 的最後指定它們的路徑。由於是放在最後位置上的選項,因此用兩個短劃線(--)隔開以前的選項和後面限定的 路徑名。

限制 git log 輸出的選項

選項 說明
-(n) 僅顯示最近的 n 條提交
--since, --after 僅顯示指定時間以後的提交。
--until, --before 僅顯示指定時間以前的提交。
--author 僅顯示指定做者相關的提交。
--committer 僅顯示指定提交者相關的提交。
--grep 僅顯示含指定關鍵字的提交
-S 僅顯示添加或移除了某個關鍵字的提交

撤消操做

注意,有些撤消操做是不可逆的.

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

$ git commit --amend  # 修改最後一次提交的信息

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

取消暫存的文件

接下來的兩個小節演示如何操做暫存區域與工做目錄中已修改的文件。

git reset HEAD <file>  #  來取消暫存

例如,你已經修改了兩個文件而且想要將它們做爲兩次獨立的修改提交,可是卻意外地輸入了 git add * 暫存了它們兩個。如何只取消暫存兩個中的一個呢?git status 命令提示了你:

$ git add *
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
modified: CONTRIBUTING.md
$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
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: CONTRIBUTING.md

雖然在調用時加上 --hard 選項能夠令 git reset 成爲一個危險的命令(譯註:可能致使 工做目錄中全部當前進度丟失!),但本例中工做目錄內的文件並不會被修改。不加選項地 調用 git reset 並不危險 — 它只會修改暫存區域。

撤消對文件的修改

git checkout -- [file]  # 把暫存區的信息覆蓋工做區的內容

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

遠程倉庫的使用

查看遠程倉庫

git remote   # 查看你已經配置的遠程倉庫服務器

origin - 這是 Git 給你克隆的倉庫服務器的默認名字

git remote -v  # 會顯示須要讀寫遠程倉庫使用的 Git 保存的簡寫與其對應的 URL

添加遠程倉庫

git remote add <shortname> <url>  # 添加一個新的遠程 Git 倉庫,同時指定一個你能夠輕鬆引用的簡寫(shortname)

例如:

$ git remote
origin
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push)

如今你能夠在命令行中使用字符串 pb 來代替整個 URL。例如,若是你想拉取 Paul 的倉庫中有但你沒有的信 息,能夠運行 git fetch pb:

$ git fetch pb
remote: Counting objects: 43, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 43 (delta 10), reused 31 (delta 5)
Unpacking objects: 100% (43/43), done.
From https://github.com/paulboone/ticgit
* [new branch] master -> pb/master
* [new branch] ticgit -> pb/ticgit

從遠程倉庫中抓取與拉取

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

若是你使用 clone 命令克隆了一個倉庫,命令會自動將其添加爲遠程倉庫並默認以 「origin」 爲簡寫。所 以,git fetch origin 會抓取克隆(或上一次抓取)後新推送的全部工做。必須注意 git fetch 命令會將 數據拉取到你的本地倉庫 - 它並不會自動合併或修改你當前的工做。當準備好時你必須手動將其合併入你的工 做。

若是你有一個分支設置爲跟蹤一個遠程分支,可使用 git pull 命令來自動的抓取而後合併遠程分支到當前分支。 這對你來講多是一個更簡單或更舒服的工做流程;默認狀況下,git clone 命令會自動設置本地 master 分支跟蹤 克隆的遠程倉庫的 master 分支(或無論是什麼名字的默認分支)。運行 git pull 一般會從最初克隆的服務器上抓 取數據並自動嘗試合併到當前所在的分支。

推送到遠程倉庫

git push [remote-name] [branchname]  # 將本分支的倉庫推送到上游

當你想要將 master 分支推送到 origin 服務器時(再次說明,克隆時一般會自動幫你設置好那兩個名 字),那麼運行這個命令就能夠將你所作的備份到服務器:

$ git push origin master

<font color=red>push前必定先要fetch和merge,要否則遠程服務器會拒絕</font> 只有當你有所克隆服務器的寫入權限,而且以前沒有人推送過期,這條命令才能生效。當你和其餘人在同一時間 克隆,他們先推送到上游而後你再推送到上游,你的推送就會毫無疑問地被拒絕。你必須先將他們的工做拉取下 來並將其合併進你的工做後才能推送。

查看遠程倉庫

git remote show [remote-name]  # 查看某一個遠程倉庫的更多信息
$ git remote show origin
* remote origin
Fetch URL: https://github.com/schacon/ticgit
Push URL: https://github.com/schacon/ticgit
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)

它一樣會列出遠程倉庫的 URL 與跟蹤分支的信息。這些信息很是有用,它告訴你正處於 master 分支,而且若是 運行 git pull,就會抓取全部的遠程引用,而後將遠程 master 分支合併到本地 master 分支。它也會列出拉取到 的全部遠程引用。

這個命令列出了當你在特定的分支上執行 git push 會自動地推送到哪個遠程分支。它也一樣地列出了哪些 遠程分支不在你的本地,哪些遠程分支已經從服務器上移除了,還有當你執行 git pull 時哪些分支會自動合 並。

遠程倉庫的移除與重命名

git remote rename [oldname] [newname]  #

若是由於一些緣由想要移除一個遠程倉庫 - 你已經從服務器上搬走了或再也不想使用某一個特定的鏡像了,又或者 某一個貢獻者再也不貢獻了 - 可使用 git remote rm

git remote rm [name]

打標籤

列出標籤

git tag # 以字母順序列出標籤

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

$ git tag -l 'v1.8.5*'
v1.8.5
v1.8.5-rc0
v1.8.5-rc1
v1.8.5-rc2
v1.8.5-rc3
v1.8.5.1
v1.8.5.2
v1.8.5.3
v1.8.5.4
v1.8.5.5

建立標籤

Git 使用兩種主要類型的標籤:

    1. 輕量標籤(lightweight) : 不會改變的分支 - 它只是一個特定提交的引用
    1. 附註標籤(annotated) : 存儲在 Git 數據庫中的一個完整對象 它們是能夠被校驗的;其中包含打標籤者的名字、電子郵件地址、日期時間;還有一個標籤信息;而且可使用 GNU Privacy Guard (GPG)簽名與驗證。

一般建議建立附註標籤,這樣你能夠擁有以上全部信息;可是若是你只是想用一個臨時的 標籤,或者由於某些緣由不想要保存那些信息,輕量標籤也是可用的。

附註標籤
git tag -a [tagName] -m [message] :  建立附註標籤

-m 選項指定了一條將會存儲在標籤中的信息。若是沒有爲附註標籤指定一條信息,Git 會運行編輯器要求你輸入信息。

git show [tagName] : 命令能夠看到標籤信息與對應的提交信息

輸出顯示了打標籤者的信息、打標籤的日期時間、附註信息,而後顯示具體的提交信息。

輕量標籤

輕量標籤本質上是將提交校驗和存儲到一個文件中 - 沒有保存任何 其餘信息。建立輕量標籤,不須要使用 -a、-s 或 -m 選項,只須要提供標籤名字:

git tag [tagName]  : 建立 輕量標籤
後期打標籤
git tag -a [tagName] [commit id]  # 爲特定的commit建立標籤

假設提交歷史是這樣的:

$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

如今,假設在 v1.2 時你忘記給項目打標籤,也就是在 「updated rakefile」 提交。你能夠在以後補上標籤。要 在那個提交上打標籤,你須要在命令的末尾指定提交的校驗和(或部分校驗和):

$ git tag -a v1.2 9fceb02
共享標籤到遠程服務器

** git push 命令並不會傳送標籤到遠程倉庫服務器上 **

建立完標籤後你必須顯式地推送標籤到共享服務器上。這個過程就像共享遠程分支同樣 - 你能夠運行:

git push origin [tagname] # 共享標籤到遠程服務器

若是想要一次性推送不少標籤,也可使用帶有 --tags 選項的 git push 命令。這將會把全部不在遠程倉庫 服務器上的標籤所有傳送到那裏。

例如:

$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new tag] v1.4 -> v1.4
* [new tag] v1.4-lw -> v1.4-lw
檢出標籤到本地倉庫

在 Git 中你並不能真的檢出一個標籤,由於它們並不能像分支同樣來回移動。若是你想要工做目錄與倉庫中特定 的標籤版本徹底同樣,可使用 git checkout -b [branchname] [tagname] 在特定的標籤上建立一個新分支:

git checkout -b [branchname] [tagname]  #  在特定的標籤上建立一個新分支
$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'

固然,若是在這以後又進行了一次提交,version2 分支會由於改動向前移動了,那麼 version2 分支就會和 v2.0.0 標籤稍微有些不一樣,這時就應該小心了。

Git 別名

Git 並不會在你輸入部分命令時自動推斷出你想要的命令。若是不想每次都輸入完整的 Git 命令,能夠經過 git config 文件來輕鬆地爲每個命令設置一個別名。

git config --global alias.[aliasname] [name]  # 爲某個命令建立別名
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status

Git 分支

分支簡介

Git 保存的不是文件的變化或者差別,而是一系列不一樣時刻的文件快照。這個特性是Git快速建立分支和快速切換分支的基礎。 這就是用空間來換時間的原理。固然空間Git也優化的很好。

在進行提交操做時,Git 會保存一個提交對象(commit object)。知道了 Git 保存數據的方式,咱們能夠很自 然的想到——該提交對象會包含一個指向暫存內容快照的指針。但不只僅是這樣,該提交對象還包含了做者的姓 名和郵箱、提交時輸入的信息以及指向它的父對象的指針。首次提交產生的提交對象沒有父對象,普通提交操做 產生的提交對象有一個父對象,而由多個分支合併產生的提交對象有多個父對象,爲了說得更加形象,咱們假設現 在有一個工做目錄,裏面包含了三個將要被暫存和提交的文件。暫存操做會爲每個文件計算校驗和SHA-1 哈希算法, 而後會把當前版本的文件快照保存到 Git倉庫中(Git 使用 blob 對象來保存它們),最終將校驗和加入到暫存區域等待提交:

$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'

當使用 git commit 進行提交操做時,Git 會先計算每個子目錄(本例中只有項目根目錄)的校驗和,而後在 Git 倉庫中這些校驗和保存爲樹對象。隨後,Git 便會建立一個提交對象,它除了包含上面提到的那些信息外, 還包含指向這個樹對象(項目根目錄)的指針。如此一來,Git 就能夠在須要的時候重現這次保存的快照。

如今,Git 倉庫中有五個對象:三個 blob 對象(保存着文件快照)、一個樹對象(記錄着目錄結構和 blob 對象 索引)以及一個提交對象(包含着指向前述樹對象的指針和全部提交信息)。

首次提交對象及其樹結構
graph LR
commit-->tree
tree-->blob1
tree-->blob2
tree-->blob3
提交對象及其父對象
graph RL
commitA-->snapshotA
commitB-->snapshotB
commitC-->snapshotC
commitC-->commitB
commitB-->commitA

Git 的分支,其實本質上僅僅是指向提交對象的可變指針。Git 的默認分支名字是 master。在屢次提交操做之 後,你其實已經有一個指向最後那個提交對象的 master 分支。它會在每次的提交操做中自動向前移動。

相關文章
相關標籤/搜索