Git的學習總結


  首先,Git是一個開源的分布式版本控制系統,用於敏捷高效地處理任何或小或大的項目。  Git 也是 Linus Torvalds 為了幫助管理 Linux 內核開發而開發的一個開放源碼的版本控制軟件。  Git 與常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本庫的方式,不必服務器端軟件的支持。

一、Git 與 svn 區別

  • 1、GIT是分布式的,SVN不是:這是GIT和其它非分布式的版本控制系統,例如SVN,CVS等,最核心的區別。

  • 2、GIT把內容按元數據方式存儲,而SVN是按文件:所有的資源控制系統都是把文件的元信息隱藏在一個類似.svn,.cvs等的文件夾里。

  • 3、GIT分支和SVN的分支不同:分支在SVN中一點不特別,就是版本庫中的另外的一個目錄。

  • 4、GIT沒有一個全局的版本號,而SVN有:目前為止這是跟SVN相比GIT缺少的最大的一個特征。

  • 5、GIT的內容完整性要優於SVN:GIT的內容存儲使用的是SHA-1哈希算法。這能確保代碼內容的完整性,確保在遇到磁盤故障和網絡問題時降低對版本庫的破壞。

 

二、Git 的基本安裝配置

  Git 的工作需要調用 curl,zlib,openssl,expat,libiconv 等庫的代碼,所以需要先安裝這些依賴工具。在有 yum 的系統上(比如 Fedora)或者有 apt-get 的系統上(比如 Debian 體系),下面就以為例Centos/RedHat,命令安裝:

$ yum install curl-devel expat-devel gettext-devel \
  openssl-devel zlib-devel

$ yum -y install git-core

$ git --version
git version 1.7.1

  

  在 Windows 平台上安裝 Git 同樣輕松,有個叫做 msysGit 的項目提供了安裝包,可以到 GitHub 的頁面上下載 exe 安裝文件並運行:

    安裝包下載地址:http://msysgit.github.io/

  完成安裝之后,就可以使用命令行的 git 工具(已經自帶了 ssh 客戶端)了,另外還有一個圖形界面的 Git 項目管理工具。在開始菜單里找到"Git"->"Git Bash",會彈出 Git 命令窗口,你可以在該窗口進行 Git 操作。

三、Git 配置

  Git 提供了一個叫做 git config 的工具,專門用來配置或讀取相應的工作環境變量。

  這些環境變量,決定了 Git 在各個環節的具體工作方式和行為。這些變量可以存放在以下三個不同的地方:

  • /etc/gitconfig 文件:系統中對所有用戶都普遍適用的配置。若使用 git config 時用 --system 選項,讀寫的就是這個文件。
  • ~/.gitconfig 文件:用戶目錄下的配置文件只適用於該用戶。若使用 git config 時用 --global 選項,讀寫的就是這個文件。
  • 當前項目的 Git 目錄中的配置文件(也就是工作目錄中的 .git/config 文件):這里的配置僅僅針對當前項目有效。每一個級別的配置都會覆蓋上層的相同配置,所以 .git/config 里的配置會覆蓋 /etc/gitconfig 中的同名變量。

  在 Windows 系統上,Git 會找尋用戶主目錄下的 .gitconfig 文件。主目錄即 $HOME 變量指定的目錄,一般都是 C:\Documents and Settings\$USER。

此外,Git 還會嘗試找尋 /etc/gitconfig 文件,只不過看當初 Git 裝在什么目錄,就以此作為根目錄來定位。

用戶信息

  配置個人的用戶名稱和電子郵件地址:

$ git config --global user.name "w3c"
$ git config --global user.email w3c@w3cschool.cn

  如果用了 --global 選項,那么更改的配置文件就是位於你用戶主目錄下的那個,以后你所有的項目都會默認使用這里配置的用戶信息。

  如果要在某個特定的項目中使用其他名字或者電郵,只要去掉 --global 選項重新配置即可,新的設定保存在當前項目的 .git/config 文件里。

文本編輯器

  設置Git默認使用的文本編輯器, 一般可能會是 Vi 或者 vim。如果你有其他偏好,比如 Emacs 的話,可以重新設置::

$ git config --global core.editor emacs

差異分析工具

  還有一個比較常用的是,在解決合並沖突時使用哪種差異分析工具。比如要改用 vimdiff 的話:

$ git config --global merge.tool vimdiff

  Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合並工具的輸出信息。

 

查看配置信息

  要檢查已有的配置信息,可以使用 git config --list 命令:

$ git config --list
user.name=Scott Chacon
user.email=schacon@gmail.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...

  有時候會看到重復的變量名,那就說明它們來自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不過最終 Git 實際采用的是最后一個。

  也可以直接查閱某個環境變量的設定,只要把特定的名字跟在后面即可,像這樣:

$ git config user.name
Scott Chacon

 

 

四、Git 工作流程 

一般工作流程如下:

  • 克隆 Git 資源作為工作目錄。
  • 在克隆的資源上添加或修改文件。
  • 如果其他人修改了,你可以更新資源。
  • 在提交前查看修改。
  • 提交修改。
  • 在修改完成后,如果發現錯誤,可以撤回提交並再次修改並提交。

下圖展示了 Git 的工作流程:

 

五、Git的基本概念

  • 工作區:就是你在電腦里能看到的目錄。
  • 暫存區:英文叫stage, 或index。一般存放在"git目錄"下的index文件(.git/index)中,所以我們把暫存區有時也叫作索引(index)。
  • 版本庫:工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。

  下面這個圖展示了工作區、版本庫中的暫存區和版本庫之間的關系:

  圖中左側為工作區,右側為版本庫。在版本庫中標記為 "index" 的區域是暫存區(stage, index),標記為 "master" 的是 master 分支所代表的目錄樹。

  圖中我們可以看出此時 "HEAD" 實際是指向 master 分支的一個"游標"。所以圖示的命令中出現 HEAD 的地方可以用 master 來替換。

  圖中的 objects 標識的區域為 Git 的對象庫,實際位於 ".git/objects" 目錄下,里面包含了創建的各種對象及內容。

  當對工作區修改(或新增)的文件執行 "git add" 命令時,暫存區的目錄樹被更新,同時工作區修改(或新增)的文件內容被寫入到對象庫中的一個新的對象中,而該對象的ID被記錄在暫存區的文件索引中。

  當執行提交操作(git commit)時,暫存區的目錄樹寫到版本庫(對象庫)中,master 分支會做相應的更新。即 master 指向的目錄樹就是提交時暫存區的目錄樹。

  當執行 "git reset HEAD" 命令時,暫存區的目錄樹會被重寫,被 master 分支指向的目錄樹所替換,但是工作區不受影響。

  當執行 "git rm --cached <file>" 命令時,會直接從暫存區刪除文件,工作區則不做出改變。

  當執行 "git checkout ." 或者 "git checkout -- <file>" 命令時,會用暫存區全部或指定的文件替換工作區的文件。這個操作很危險,會清除工作區中未添加到暫存區的改動。

  當執行 "git checkout HEAD ." 或者 "git checkout HEAD <file>" 命令時,會用 HEAD 指向的 master 分支中的全部或者部分文件替換暫存區和以及工作區中的文件。這個命令也是極具危險性的,因為不但會清除工作區中未提交的改動,也會清除暫存區中未提交的改動。

 

六、Git 創建倉庫

  使用您本地當前的目錄作為Git倉庫,我們只需初始化它:

git init

  

  使用我們指定目錄作為Git倉庫:

git init newrepo

 

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

  如果當前目錄下有幾個文件想要納入版本控制,需要先用 git add 命令告訴 Git 開始對這些文件進行跟蹤,然后提交:

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

 

 從現有倉庫克隆

  克隆倉庫的命令格式為:git clone [url]  。比如,要克隆 Ruby 語言的 Git 代碼倉庫 Grit,可以用下面的命令:

$ git clone git://github.com/schacon/grit.git

 

  執行該命令后,會在當前目錄下創建一個名為grit的目錄,其中包含一個 .git 的目錄,用於保存下載下來的所有版本記錄。如果要自己定義要新建的項目目錄名稱,可以在上面的命令末尾指定新的名字:

$ git clone git://github.com/schacon/grit.git mygrit

 

 

七、Git 的基本操作

  (1)獲取與創建項目命令

   1、git init

    用 git init 在目錄中創建新的 Git 倉庫。 你可以在任何時候、任何目錄中這么做,完全是本地化的。

    在目錄中執行 git init,就可以創建一個 Git 倉庫了。比如我們創建 abc項目:

$ mkdir abc
$ cd abc
$ git init
Initialized empty Git repository in /www/abc/.git/
# 在 /www/abc/.git/ 目錄初始化空 Git 倉庫完畢。

   現在你可以看到在你的項目目錄中有個 .git 的子目錄。 這就是你的 Git 倉庫了,所有有關你的此項目的快照數據都存放在這里。

ls -a
.    ..  .git

  2、git clone

    使用 git clone 拷貝一個 Git 倉庫到本地,讓自己能夠查看該項目,或者進行修改。

    如果你需要與他人合作一個項目,或者想要復制一個項目,看看代碼,你就可以克隆那個項目。 執行命令: git clone [url]。其中,[url] 為你想要復制的項目,就可以了。例如:

$ git clone git://github.com/schacon/simplegit.git
Initialized empty Git repository in /private/tmp/simplegit/.git/
remote: Counting objects: 100, done.
remote: Compressing objects: 100% (86/86), done.
remote: Total 100 (delta 35), reused 0 (delta 0)
Receiving objects: 100% (100/100), 9.51 KiB, done.
Resolving deltas: 100% (35/35), done.
$ cd simplegit/
$ ls
README   Rakefile lib

    上述操作將復制該項目的全部記錄。

$ ls -a
.        ..       .git     README   Rakefile lib
$ cd .git
$ ls
HEAD        description info        packed-refs
branches    hooks       logs        refs
config      index       objects

  默認情況下,Git 會按照你提供的 URL 所指示的項目的名稱創建你的本地項目目錄。 通常就是該 URL 最后一個 / 之后的項目名稱。如果你想要一個不一樣的名字, 你可以在該命令后加上你想要的名稱。

 

  (2)基本快照

    1、git add

     git add 命令可將該文件添加到緩存,如我們添加以下兩個文件:

$ touch README
$ touch hello.php
$ ls
README      hello.php
$ git status -s
?? README
?? hello.php
$ 

  

    git status 命令用於查看項目的當前狀態。接下來我們執行 git add 命令來添加文件:

$ git add README hello.php 

    現在我們再執行 git status,就可以看到這兩個文件已經加上去了:

$ git status -s
A  README
A  hello.php
$ 

  新項目中,添加所有文件很普遍,可以在當前工作目錄執行命令:git add .。現在我們改個文件,再執行一下 git status:

$ vim README
$ git status -s
AM README
A  hello.php

  "AM" 狀態的意思是,這個文件在我們將它添加到緩存之后又有改動。改動后我們在執行 git add 命令將其添加到緩存中:

$ git add .
$ git status -s
A  README
A  hello.php

    當你要將你的修改包含在即將提交的快照里的時候,需要執行 git add。

 

 

  2、git status

    git status 以查看在你上次提交之后是否有修改。

    我演示該命令的時候加了 -s 參數,以獲得簡短的結果輸出。如果沒加該參數會詳細輸出內容:

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

  new file:   README
    new file:   hello.php

  

  3、git diff

  執行 git diff 來查看執行 git status 的結果的詳細信息。

  git diff 命令顯示已寫入緩存與已修改但尚未寫入緩存的改動的區別。git diff 有兩個主要的應用場景。

  • 尚未緩存的改動:git diff
  • 查看已緩存的改動: git diff --cached
  • 查看已緩存的與未緩存的所有改動:git diff HEAD
  • 顯示摘要而非整個 diff:git diff --stat

  在 hello.php 文件中輸入以下內容:

<?php echo 'www.abc.cn'; ?>
$ git status -s
A  README
AM hello.php
$ git diff
diff --git a/hello.php b/hello.php
index e69de29..d1a9166 100644
--- a/hello.php
+++ b/hello.php
@@ -0,0 +1,3 @@
+<?php +echo 'www.abc.cn'; +?>

  git status顯示你上次提交更新至后所更改或者寫入緩存的改動, 而 git diff 一行一行地顯示這些改動具體是啥。接下來我們來查看下 git diff --cached 的執行效果:

$ git add hello.php 
$ git status -s
A  README
A  hello.php
$ git diff --cached
diff --git a/README b/README
new file mode 100644
index 0000000..704cce7
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+w3cschool.cn
diff --git a/hello.php b/hello.php
new file mode 100644
index 0000000..d1a9166
--- /dev/null
+++ b/hello.php
@@ -0,0 +1,3 @@
+<?php +echo 'www.abc.cn'; +?>

  

  4、git commit

    使用 git add 命令將想要快照的內容寫入了緩存, 而執行 git commit 記錄緩存區的快照。

    Git 為你的每一個提交都記錄你的名字與電子郵箱地址,所以第一步需要配置用戶名和郵箱地址。

$ git config --global user.name 'w3cschool'
$ git config --global user.email w3c@w3cschool.cn

 

  接下來我們寫入緩存,並提交對 hello.php 的所有改動。在首個例子中,我們使用 -m 選項以在命令行中提供提交注釋。

$ git add hello.php
$ git status -s
A  README
A  hello.php
$ git commit -m 'test comment from abc.cn'
[master (root-commit) 85fc7e7] test comment from abc.cn
 2 files changed, 4 insertions(+)
 create mode 100644 README
 create mode 100644 hello.php

  現在我們已經記錄了快照。如果我們再執行 git status:

 $ git status
# On branch master
nothing to commit (working directory clean)

  以上輸出說明我們在最近一次提交之后,沒有做任何改動,是一個"干凈的工作目錄"。

  如果你沒有設置 -m 選項,Git 會嘗試為你打開一個編輯器以填寫提交信息。 如果 Git 在你對它的配置中找不到相關信息,默認會打開 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: # (use "git reset HEAD ..." to unstage) # # modified: hello.php # ~ ~ ".git/COMMIT_EDITMSG" 9L, 257C

  如果你覺得 git add 提交緩存的流程太過繁瑣,Git 也允許你用 -a 選項跳過這一步。命令格式如下:git commit -a

$ git commit -am 'changes to hello file'
[master 78b2670] changes to hello file
 1 files changed, 2 insertions(+), 1 deletions(-)

  

  5、git reset HEAD

    git reset HEAD 命令用於取消緩存已緩存的內容。

    這里我們有兩個最近提交之后又有所改動的文件。我們將兩個都緩存,並取消緩存其中一個。

$ git status -s
 M README
 M hello.php
$ git add .
$ git status -s
M  README
M  hello.pp
$ git reset HEAD -- hello.php 
Unstaged changes after reset:
M hello.php
$ git status -s
M  README
 M hello.php

  現在你執行 git commit 將只記錄 README 文件的改動,並不含現在並不在緩存中的 hello.rb。

 

  6、git rm

    git rm 將文件從緩存區中移除。

    如我們刪除 hello.PHP文件:

 $ git rm hello.php 
rm 'hello.php'
$ ls
README

  默認情況下,git rm file 會將文件從緩存區和你的硬盤中(工作目錄)刪除。 如果要在工作目錄中留着該文件,可以使用命令:

git rm --cached。

 

  7、git mv

   git mv 命令做得所有事情就是 git rm --cached, 重命名磁盤上的文件,然后再執行 git add 把新文件添加到緩存區。因此,雖然有 git mv 命令,但它有點多余 。

 

八、Git 分支管理

  幾乎每一種版本控制系統都以某種形式支持分支。使用分支意味着你可以從開發主線上分離開來,然后在不影響主線的同時繼續工作。

  有人把 Git 的分支模型稱為"必殺技特性",而正是因為它,將 Git 從版本控制系統家族里區分出來。創建分支命令:

git branch (branchname)

  切換分支命令:

git checkout (branchname)

  

  當你切換分支的時候,Git 會用該分支的最后提交的快照替換你的工作目錄的內容, 所以多個分支不需要多個目錄。合並分支命令:

git merge 

  你可以多次合並到統一分支, 也可以選擇在合並之后直接刪除被並入的分支。

 

  

  列出分支

    列出分支基本命令:git branch   。沒有參數時,git branch 會列出你在本地的分支。

$ git branch
* master

    此例的意思就是,我們有一個叫做"master"的分支,並且該分支是當前分支。當你執行 git init 的時候,缺省情況下 Git 就會為你創建"master"分支。如果我們要手動創建一個分支,並切換過去。執行 git branch (branchname) 即可。

$ git branch testing
$ git branch
* master
  testing

  現在我們可以看到,有了一個新分支 testing。當你以此方式在上次提交更新之后創建了新分支,如果后來又有更新提交, 然后又切換到了"testing"分支,Git 將還原你的工作目錄到你創建分支時候的樣子接下來我們將演示如何切換分支,我們用 git checkout (branch) 切換到我們要修改的分支。

$ ls
README
$ echo 'abc.cn' > test.txt
$ git add .
$ git commit -m 'add test.txt'
[master 048598f] add test.txt
 2 files changed, 1 insertion(+), 3 deletions(-)
 delete mode 100644 hello.php
 create mode 100644 test.txt
$ ls
README       test.txt
$ git checkout testing
Switched to branch 'testing'
$ ls
README      hello.php

  

  當我們切換到"testing"分支的時候,我們添加的新文件test.txt被移除了, 原來被刪除的文件hello.PHP文件又出現了。切換回"master"分支的時候,它們有重新出現了。

$ git checkout master
Switched to branch 'master'
$ ls
README        test.txt

  我們也可以使用 git checkout -b (branchname) 命令來創建新分支並立即切換到該分支下,從而在該分支中操作。

$ git checkout -b newtest
Switched to a new branch 'newtest'
$ git rm test2.txt 
rm 'test2.txt'
$ ls
README      test.txt
$ git commit -am 'removed test2.txt'
[newtest 556f0a0] removed test2.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test2.txt
$ git checkout master
Switched to branch 'master'
$ ls
README        test.txt    test2.txt

  

    如你所見,我們創建了一個分支,在該分支的上下文中移除了一些文件,然后切換回我們的主分支,那些文件又回來了。

    使用分支將工作切分開來,從而讓我們能夠在不同上下文中做事,並來回切換。

  刪除分支

    刪除分支命令:git branch -d (branchname)  .例如我們要刪除"testing"分支:

$ git branch
* master
  testing
$ git branch -d testing
Deleted branch testing (was 85fc7e7).
$ git branch
* master

  

  分支合並

    一旦某分支有了獨立內容,你終究會希望將它合並回到你的主分支。 你可以使用以下命令將任何分支合並到當前分支中去:

git merge
$ git branch
* master
  newtest
$ ls
README       test.txt    test2.txt
$ git merge newtest
Updating 2e082b7..556f0a0
Fast-forward
 test2.txt | 1 -
 1 file changed, 1 deletion(-)
 delete mode 100644 test2.txt
$ ls
README      test.txt

  以上實例中我們將 newtest 分支合並到主分支去,test2.txt 文件被刪除。

 

  合並沖突

    合並並不僅僅是簡單的文件添加、移除的操作,Git 也會合並修改。

$ git branch
* master
$ cat test.txt
abc.cn

  首先,我們創建一個叫做"change_site"的分支,切換過去,我們將內容改為 www.abc.cn 。

$ git checkout -b change_site
Switched to a new branch 'change_site'
$ vim test.txt 
$ head -1 test.txt 
www.abc.cn
$ git commit -am 'changed the site'
[change_site d7e7346] changed the site
 1 file changed, 1 insertion(+), 1 deletion(-)

  將修改的內容提交到 "change_site" 分支中。 現在,假如切換回 "master" 分支我們可以看內容恢復到我們修改前的,我們再次修改test.txt文件。

$ git checkout master
Switched to branch 'master'
$ head -1 test.txt 
abc.cn
$ vim test.txt 
$ cat test.txt
abc.cn
新增加一行
$ git diff
diff --git a/test.txt b/test.txt
index 704cce7..f84c2a4 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
 bcd.cn
+新增加一行
$ git commit -am '新增加一行'
[master 14b4dca] 新增加一行
 1 file changed, 1 insertion(+)

 

  

 $ git merge change_site
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
$ cat test.txt 
<<<<<<< HEAD abc.cn 新增加一行 ======= www.abc.cn >>>>>>> change_site

  現在這些改變已經記錄到我的 "master" 分支了。接下來我們將 "change_site" 分支合並過來。

  我們將前一個分支合並到 "master" 分支,一個合並沖突就出現了,接下來我們需要手動去修改它。

$ vim test.txt 
$ cat test.txt 
www.abc.cn
新增加一行
$ git diff
diff --cc test.txt
index f84c2a4,bccb7c2..0000000
--- a/test.txt
+++ b/test.txt
@@@ -1,2 -1,1 +1,2 @@@
- w3cschool.cn
+ www.abc.cn
 +新增加一行

 

  在 Git 中,我們可以用 git add 要告訴 Git 文件沖突已經解決

$ git status -s
UU test.txt
$ git add test.txt 
$ git status -s
M  test.txt
$ git commit
[master 88afe0e] Merge branch 'change_site'

 

九、Git 查看提交歷史

    在使用 Git 提交了若干更新之后,又或者克隆了某個項目,想回顧下提交歷史,我們可以使用 git log 命令查看。針對我們前一章節的操作,使用 git log 命令列出歷史提交記錄如下:

$ git log
commit 88afe0e02adcdfea6844bb627de97da21eb10af1
Merge: 14b4dca d7e7346
Author: abc<abc.cn>
Date:   Sun Mar 1 15:03:42 2015 +0800

    Merge branch 'change_site'
    
    Conflicts:
        test.txt

commit 14b4dcadbdc847207651d5a9fae0d315057f346e
Author:  abc<abc.cn>
Date:   Sun Mar 1 14:53:15 2015 +0800

    新增加一行

commit d7e734640da06055e107eaf29cf350b3f1de1c2c
Author: abc<abc.cn>
Date:   Sun Mar 1 14:48:57 2015 +0800

    changed the site

commit 556f0a0637978097b82287ac665a717623b21f3f
Author:  abc<abc.cn>
Date:   Sun Mar 1 14:40:34 2015 +0800

    removed test2.txt

  我們可以用 --oneline 選項來查看歷史記錄的簡潔的版本。

$ git log --oneline
88afe0e Merge branch 'change_site'
14b4dca 新增加一行
d7e7346 changed the site
556f0a0 removed test2.txt
2e082b7 add test2.txt
048598f add test.txt
85fc7e7 test comment from abc.cn

  我們還可以用 --graph 選項,查看歷史中什么時候出現了分支、合並。以下為相同的命令,開啟了拓撲圖選項:

$ git log --oneline --graph
*   88afe0e Merge branch 'change_site'
|\  
| * d7e7346 changed the site
* | 14b4dca 新增加一行
|/  
* 556f0a0 removed test2.txt
* 2e082b7 add test2.txt
* 048598f add test.txt
* 85fc7e7 test comment from abc.cn

  你也可以用 '--reverse'參數來逆向顯示所有日志。

$ git log --reverse --oneline
85fc7e7 test comment from abc.cn
048598f add test.txt
2e082b7 add test2.txt
556f0a0 removed test2.txt
d7e7346 changed the site
14b4dca 新增加一行
88afe0e Merge branch 'change_site'

  如果只想查找指定用戶的提交日志可以使用命令:git log --author , 例如,比方說我們要找 Git 源碼中 Linus 提交的部分:

$ git log --author=Linus --oneline -5
81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory
3bb7256 make "index-pack" a built-in
377d027 make "git pack-redundant" a built-in
b532581 make "git unpack-file" a built-in
112dd51 make "mktag" a built-in

  

  如果你要指定日期,可以執行幾個選項:--since 和 --before,但是你也可以用 --until 和 --after.例如,如果我要看 Git 項目中三周前且在四月十八日之后的所有提交,我可以執行這個(我還用了 --no-merges 選項以隱藏合並提交):

$ git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges
5469e2d Git 1.7.1-rc2
d43427d Documentation/remote-helpers: Fix typos and improve language
272a36b Fixup: Second argument may be any arbitrary string
b6c8d2d Documentation/remote-helpers: Add invocation section
5ce4f4e Documentation/urls: Rewrite to accomodate transport::address
00b84e9 Documentation/remote-helpers: Rewrite description
03aa87e Documentation: Describe other situations where -z affects git diff
77bc694 rebase-interactive: silence warning when no commits rewritten
636db2c t3301: add tests to use --format="%N"

 

 

十、Git 標簽

  如果你達到一個重要的階段,並希望永遠記住那個特別的提交快照,你可以使用 git tag 給它打上標簽。

  比如說,我們想為我們的 w3cschoolcc 項目發布一個"1.0"版本。 我們可以用 git tag -a v1.0 命令給最新一次提交打上(HEAD)"v1.0"的標簽。-a 選項意為"創建一個帶注解的標簽"。 不用 -a 選項也可以執行的,但它不會記錄這標簽是啥時候打的,誰打的,也不會讓你添加個標簽的注解。 我推薦一直創建帶注解的標簽。

$ git tag -a v1.0 

  

  當你執行 git tag -a 命令時,Git 會打開你的編輯器,讓你寫一句標簽注解,就像你給提交寫注解一樣。現在,注意當我們執行 git log --decorate 時,我們可以看到我們的標簽了:

$ git log --oneline --decorate --graph
*   88afe0e (HEAD, tag: v1.0, master) Merge branch 'change_site'
|\  
| * d7e7346 (change_site) changed the site
* | 14b4dca 新增加一行
|/  
* 556f0a0 removed test2.txt
* 2e082b7 add test2.txt
* 048598f add test.txt
* 85fc7e7 test comment from abc.cn

 

  如果我們忘了給某個提交打標簽,又將它發布了,我們可以給它追加標簽。例如,假設我們發布了提交 85fc7e7(上面實例最后一行),但是那時候忘了給它打標簽。 我們現在也可以:

$ git tag -a v0.9 85fc7e7
$ git log --oneline --decorate --graph
*   88afe0e (HEAD, tag: v1.0, master) Merge branch 'change_site'
|\  
| * d7e7346 (change_site) changed the site
* | 14b4dca 新增加一行
|/  
* 556f0a0 removed test2.txt
* 2e082b7 add test2.txt
* 048598f add test.txt
* 85fc7e7 (tag: v0.9) test comment from abc.cn

  如果我們要查看所有標簽可以使用以下命令:

$ git tag
v0.9
v1.0

  指定標簽信息命令:

git tag -a <tagname> -m "abc.cn標簽"

  PGP簽名標簽命令:

git tag -s <tagname> -m "abc.cn標簽"

 

十一、Git 遠程倉庫

  Git 並不像 svn 那樣有個中心服務器。

  目前我們使用到的 Git 命令都是在本地執行,如果你想通過 Git 分享你的代碼或者與其他開發人員合作。 你就需要將數據放到一台其他開發人員能夠連接的服務器上。

  添加遠程庫

    要添加一個新的遠程倉庫,可以指定一個簡單的名字,以便將來引用,命令格式如下:git remote add [shortname] [url]  。本例以Github為例作為遠程倉庫,如果你沒有Github可以在官網Https://github.com/注冊。

   由於你的本地Git倉庫和GitHub倉庫之間的傳輸是通過ssh加密的,所以我們需要配置驗證信息:使用以下命令生成SSH Key:

$ ssh-keygen -t rsa -C "youremail@example.com"

  

  后面的your_email@youremail.com改為你在github上注冊的郵箱,之后會要求確認路徑和輸入密碼,我們這使用默認的一路回車就行。成功的話會在~/下生成.ssh文件夾,進去,打開id_rsa.pub,復制里面的key。

  回到github上,進入 Account Settings(賬戶配置),左邊選擇SSH Keys,Add SSH Key,title隨便填,粘貼在你電腦上生成的key。

  為了驗證是否成功,輸入以下命令:

$ ssh -T git@github.com
Hi WongJay! You've successfully authenticated, but GitHub does not provide shell access.

  

  以下命令說明我們已成功連上 Github。之后登錄后點擊" New repository " 如下圖所示:

 

  之后在在Repository name 填入 w3cschool.cn(遠程倉庫名) ,其他保持默認設置,點擊"Create repository"按鈕,就成功地創建了一個新的Git倉庫:

  創建成功后,顯示如下信息:

  

   以上信息告訴我們可以從這個倉庫克隆出新的倉庫,也可以把本地倉庫的內容推送到GitHub倉庫。現在,我們根據GitHub的提示,在本地的倉庫下運行命令:

$ ls
README
W3Cschool教程測試.txt
test.txt
$ git remote add origin git@github.com:WongJay/w3cschool.cn.git
$ git push -u origin master
Counting objects: 21, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (21/21), 1.73 KiB | 0 bytes/s, done.
Total 21 (delta 4), reused 0 (delta 0)
To git@github.com:WongJay/w3cschool.cn.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

  

  以下命令請根據你在Github成功創建新倉庫的地方復制,而不是根據我提供的命令,因為我們的Github用戶名不一樣,倉庫名也不一樣。接下來我們返回 Github 創建的倉庫,就可以看到文件已上傳到Github上:

  查看當前的遠程庫

    要查看當前配置有哪些遠程倉庫,可以用命令:

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

  執行時加上 -v 參數,你還可以看到每個別名的實際鏈接地址。

提取遠程倉庫

  Git 有兩個命令用來提取遠程倉庫的更新。

    1、從遠程倉庫下載新分支與數據:

git fetch

    該命令執行完后需要執行git merge 遠程分支到你所在的分支。

2、從遠端倉庫提取數據並嘗試合並到當前分支:

git pull

  該命令就是在執行 git fetch 之后緊接着執行 git merge 遠程分支到你所在的任意分支。假設你配置好了一個遠程倉庫,並且你想要提取更新的數據,你可以首先執行 git fetch [alias] 告訴 Git 去獲取它有你沒有的數據,然后你可以執行 git merge [alias]/[branch] 以將服務器上的任何更新(假設有人這時候推送到服務器了)合並到你的當前分支。

  接下來我們在 Github 上點擊"w3cschoolW3Cschool教程測試.txt" 並在線修改它。之后我們在本地更新修改。

$ git fetch origin
Warning: Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts.
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:WongJay/w3cschool.cn
   7d2081c..f5f3Dd5  master     -> origin/master

 

  以上信息"7d2081c..f5f3dd5 master -> origin/master" 說明 master 分支已被更新,我們可以使用以下命令將更新同步到本地:

$ git merge origin/master
Updating 7d2081c..f5f3dd5
Fast-forward
 "w3cschool\350\217\234\351\270\237\346\225\231\347\250\213\346\265\213\350\257\225.txt" | 1 +
 1 file changed, 1 insertion(+)

 

推送到遠程倉庫

  推送你的新分支與數據到某個遠端倉庫命令: git push [alias] [branch]  。以上命令將你的 [branch] 分支推送成為 [alias] 遠程倉庫上的 [branch] 分支,實例如下。

$ git merge origin/master
Updating 7d2081c..f5f3dd5
Fast-forward
 "w3cschool\350\217\234\351\270\237\346\225\231\347\250\213\346\265\213\350\257\225.txt" | 1 +
 1 file changed, 1 insertion(+)
bogon:w3cschoolcc WongJay$ vim w3cschoolW3Cschool教程測試.txt 
bogon:w3cschoolcc WongJay$ git push origin master
Everything up-to-date

 

刪除遠程倉庫

  刪除遠程倉庫你可以使用命令:git remote rm [別名]

$ git remote -v
origin  git@github.com:WongJay/w3cschool.cn.git (fetch)
origin   git@github.com:WongJay/w3cschool.cn.git (push)
$ git remote add origin2 git@github.com:WongJay/w3cschool.cn.git
$ git remote -v
origin   git@github.com:WongJay/w3cschool.cn.git (fetch)
origin   git@github.com:WongJay/w3cschool.cn.git (push)
origin2   git@github.com:WongJay/w3cschool.cn.git (fetch)
origin2  git@github.com:WongJay/w3cschool.cn.git (push)
$ git remote rm origin2
$ git remote -v
origin  git@github.com:WongJay/w3cschool.cn.git (fetch)
origin   git@github.com:WongJay/w3cschool.cn.git (push)

 

十二、Git 服務器搭建

  

  接下來我們將以 Centos 為例搭建 Git 服務器。

1、安裝Git

$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel
$ yum install git

接下來我們 創建一個git用戶組和用戶,用來運行git服務:

$ groupadd git
$ adduser git -g git

 

2、創建證書登錄

  收集所有需要登錄的用戶的公鑰,公鑰位於id_rsa.pub文件中,把我們的公鑰導入到/home/git/.ssh/authorized_keys文件里,一行一個。

  如果沒有該文件創建它:

$ cd /home/git/
$ mkdir .ssh
$ chmod 700 .ssh
$ touch .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys

 

 

3、初始化Git倉庫

  首先我們選定一個目錄作為Git倉庫,假定是/home/gitrepo/w3cschoolcn.git,在/home/gitrepo目錄下輸入命令:

$ cd /home
$ mkdir gitrepo
$ chown git:git gitrepo/
$ cd gitrepo

$ git init --bare w3cschoolcn.git
Initialized empty Git repository in /home/gitrepo/w3cschoolcn.git/

 

  以上命令Git創建一個空倉庫,服務器上的Git倉庫通常都以.git結尾。然后,把倉庫所屬用戶改為git:

$ chown -R git:git w3cschoolcn.git

 

4、克隆倉庫

$ git clone git@192.168.45.4:/home/gitrepo/w3cschoolcn.git
Cloning into 'w3cschoolcn'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

192.168.45.4 為 Git 所在服務器 ip ,你需要將其修改為你自己的 Git 服務 ip。

這樣我們的 Git 服務器安裝就完成了,接下來我們可以禁用 git 用戶通過shell登錄,可以通過編輯/etc/passwd文件完成。找到類似下面的一行:

git:x:503:503::/home/git:/bin/Bash

改為:

git:x:503:503::/home/git:/sbin/nologin

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM