第七課 Git差異比對
內容提要:顯示項目的兩個不同版本之間的差異,或者顯示指定文件的不同之處
在‘git日誌’一課中,我們通過'git log -p'命令來顯示每一次提交與其父節點提交內容之間快照的差異。這節課介紹的'diff'命令會實現類似的功能---用一種統一的格式來顯示兩個快照或文件之間的差異。這節課就向你展示如何使用diff命令。
查看變更還未載入(changed but unstaged)的文件比對
最常見的一種情況是使用'git diff'查看工作目錄中某個還未載入(stage)的文件的差異。
實驗方案:
1.修改一下simplegit.rb,添加一個方法
2.然後在README文件中添加一個作者
3.然後我們用'git add'命令把README文件載入(stage)
4.運行'git status'會顯示README載入了,而simplegit.rb只是修改了還未載入。
$ vim lib/simplegit.rb
$ vim README
$ git add README
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: lib/simplegit.rb
#
$ vim README
$ git add README
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: lib/simplegit.rb
#
那麼,我現在想查看一下對simplegit.rb文件究竟做了什麼改動?在我載入之前怎麼查看這些改動的內容呢?答案是隻需運行不帶任何參數的'git diff'命令即可:
$ git diff
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..8ac6604 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -25,6 +25,10 @@ class SimpleGit
command("git log -n 25 #{treeish}")
end
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..8ac6604 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -25,6 +25,10 @@ class SimpleGit
command("git log -n 25 #{treeish}")
end
+ def log_single(branch = 'master')
+ command("git log --pretty=oneline #{branch}")
+ end
+
def blame(path)
command("git blame #{path}")
end
+ command("git log --pretty=oneline #{branch}")
+ end
+
def blame(path)
command("git blame #{path}")
end
這樣就可以看到我添加到文件中的內容,現在我可以決定是不是要將其載入了。注意,README文件的修改並沒有顯示出來。
查看載入(stage)而並未提交(commit)的變更
爲了查看載入(staged)而並未提交(not committed)的內容差異,可以使用'git diff --stage'命令(在git 1.6之前的版本中,使用'--cached')
$ git diff --staged
diff --git a/README b/README
index c526f88..879f0d4 100644
--- a/README
+++ b/README
@@ -8,3 +8,4 @@ It is an example for the Git Peepcode book that I'm currently writin
Author : Scott Chacon ([email protected])
Orange Peel Chacon ([email protected])
Magnus O. Chacon ([email protected])
+ Josephine Chacon ([email protected])
diff --git a/README b/README
index c526f88..879f0d4 100644
--- a/README
+++ b/README
@@ -8,3 +8,4 @@ It is an example for the Git Peepcode book that I'm currently writin
Author : Scott Chacon ([email protected])
Orange Peel Chacon ([email protected])
Magnus O. Chacon ([email protected])
+ Josephine Chacon ([email protected])
適應情形:在運行git commit(不帶'-a')之前,查看所有載入而未提交的變更內容。
查看在最後一次提交之後的所有變更
現在,如果你想查看最後一次提交之後工作目錄中文件的變更,你可以在git diff之後加一個HEAD來進行比對:
$ git diff HEAD
diff --git a/README b/README
index c526f88..879f0d4 100644
--- a/README
+++ b/README
@@ -8,3 +8,4 @@ It is an example for the Git Peepcode book that I'm currently writin
Author : Scott Chacon ([email protected])
Orange Peel Chacon ([email protected])
Magnus O. Chacon ([email protected])
+ Josephine Chacon ([email protected])
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..8ac6604 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -25,6 +25,10 @@ class SimpleGit
command("git log -n 25 #{treeish}")
end
diff --git a/README b/README
index c526f88..879f0d4 100644
--- a/README
+++ b/README
@@ -8,3 +8,4 @@ It is an example for the Git Peepcode book that I'm currently writin
Author : Scott Chacon ([email protected])
Orange Peel Chacon ([email protected])
Magnus O. Chacon ([email protected])
+ Josephine Chacon ([email protected])
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..8ac6604 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -25,6 +25,10 @@ class SimpleGit
command("git log -n 25 #{treeish}")
end
+ def log_single(branch = 'master')
+ command("git log --pretty=oneline #{branch}")
+ end
+
def blame(path)
command("git blame #{path}")
end
+ command("git log --pretty=oneline #{branch}")
+ end
+
def blame(path)
command("git blame #{path}")
end
適用情形:在運行'git commit -a'之前。顯示所有載入的和未載入的變更。
在本教程的'intermediate'一課中會詳細講述HEAD在git中的含義。在這裏要注意的一點是,HEAD的含義跟SVN中的HEAD含義大不相同,在git中HEAD與你目前所處分枝的最後一次提交相關。與每個用戶的本地倉庫相關,在不同分枝間切換時它也會發生改變。
上面是使用'diff'時最常用的三條命令。
從一個特定點開始文件的修改情況
這也是最常見的一個問題。譬如,如何查看創建v1.6這個標籤之後README文件所發生的修改呢,可以這樣:
$ git diff v1.6.0 -- README
diff --git a/README b/README
index 548142c..5fa41b7 100644
--- a/README
+++ b/README
@@ -24,7 +24,7 @@ It was originally written by Linus Torvalds with help of a group o
hackers around the net. It is currently maintained by Junio C Hamano.
diff --git a/README b/README
index 548142c..5fa41b7 100644
--- a/README
+++ b/README
@@ -24,7 +24,7 @@ It was originally written by Linus Torvalds with help of a group o
hackers around the net. It is currently maintained by Junio C Hamano.
Please read the file INSTALL for installation instructions.
-See Documentation/tutorial.txt to get started, then see
+See Documentation/gittutorial.txt to get started, then see
Documentation/everyday.txt for a useful minimum set of commands,
and "man git-commandname" for documentation of each command.
-See Documentation/tutorial.txt to get started, then see
+See Documentation/gittutorial.txt to get started, then see
Documentation/everyday.txt for a useful minimum set of commands,
and "man git-commandname" for documentation of each command.
上面就顯示出了工作目錄中README文件的版本差異--如果你做了本地修改,載入或未載入,都會在這次比對中顯示出來。
兩次提交的差異比對
如果你想對兩次快照做差異比對,也即項目的兩個版本之間比對--直接在git diff後跟上要比對的兩個版本號即可:
如果這兩個版本分別在兩個目錄中的話,直接運行unix的'diff'工具進行比對也可以。
$ git diff v1.0 v1.1
上節課在介紹log命令時講過格式化參數,譬如-stat,在這裏也可以對git diff命令加這樣的參數,顯示某些統計數,下面是顯示v1.6.1.1和v1.6.1.2兩個版本之間差異的統計數字:
$ git diff v1.6.1.1 v1.6.1.2 --stat
Documentation/RelNotes-1.6.1.2.txt | 39 +++++++++++++
Documentation/config.txt | 4 +-
Documentation/git-ls-tree.txt | 8 +++-
GIT-VERSION-GEN | 2 +-
RelNotes | 2 +-
builtin-commit.c | 6 ++
builtin-gc.c | 8 ++-
builtin-grep.c | 15 +++++-
builtin-log.c | 28 +++++++++-
builtin-ls-tree.c | 7 ++-
builtin-send-pack.c | 43 +++++++--------
diffcore-rename.c | 9 +++-
git-sh-setup.sh | 2 +-
sha1_file.c | 3 +-
sha1_name.c | 2 +-
t/t2300-cd-to-toplevel.sh | 4 +-
t/t4014-format-patch.sh | 52 +++++++++++++++++-
t/t5519-push-alternates.sh | 106 ++++++++++++++++++++++++++++++++++++
t/t7002-grep.sh | 7 +++
test-path-utils.c | 2 +-
20 files changed, 306 insertions(+), 43 deletions(-)
Documentation/RelNotes-1.6.1.2.txt | 39 +++++++++++++
Documentation/config.txt | 4 +-
Documentation/git-ls-tree.txt | 8 +++-
GIT-VERSION-GEN | 2 +-
RelNotes | 2 +-
builtin-commit.c | 6 ++
builtin-gc.c | 8 ++-
builtin-grep.c | 15 +++++-
builtin-log.c | 28 +++++++++-
builtin-ls-tree.c | 7 ++-
builtin-send-pack.c | 43 +++++++--------
diffcore-rename.c | 9 +++-
git-sh-setup.sh | 2 +-
sha1_file.c | 3 +-
sha1_name.c | 2 +-
t/t2300-cd-to-toplevel.sh | 4 +-
t/t4014-format-patch.sh | 52 +++++++++++++++++-
t/t5519-push-alternates.sh | 106 ++++++++++++++++++++++++++++++++++++
t/t7002-grep.sh | 7 +++
test-path-utils.c | 2 +-
20 files changed, 306 insertions(+), 43 deletions(-)
還可以深入查看某個具體文件的變更比對:
$ git diff v1.6.1.1 v1.6.1.2 -- sha1_file.c
diff --git a/sha1_file.c b/sha1_file.c
index 52d1ead..ce5ea12 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2337,7 +2337,8 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const c
static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
void *buf, unsigned long len, time_t mtime)
{
- int fd, size, ret;
+ int fd, ret;
+ size_t size;
unsigned char *compressed;
z_stream stream;
char *filename;
diff --git a/sha1_file.c b/sha1_file.c
index 52d1ead..ce5ea12 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2337,7 +2337,8 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const c
static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
void *buf, unsigned long len, time_t mtime)
{
- int fd, size, ret;
+ int fd, ret;
+ size_t size;
unsigned char *compressed;
z_stream stream;
char *filename;
執行之後會顯示sha1_file.c文件在v1.6.1.1和v1.6.1.2兩個版本之間的比對結果。
在合併某分枝前查看變更內容
這是個比較奇怪的問題,因爲如果你開始是工作在一個主分枝上,而後生成了兩個分支,如果直接對比快照的話,結果只會顯示從一個狀態到另一個狀態的差異比對結果。
舉例來說,如果你創建了一個'dev'的分枝,進入這個分枝給lib/simplegit.rb添加了一個函數,然後回到了'master'分枝,刪除了README文件的一行,然後運行:
結果會顯示你給某個文件中添加了方法,還往README文件添加了一行內容。爲什麼會這樣?因爲對'dev'分枝來說,README文件還是原樣,而在'master'上,你已經刪掉了一行,這樣直接對兩個快照進行對比就好似'dev'分枝添加了一行進去一樣。你想查看的實際上是在創建dev分枝之後在這條分枝上的差異對比,所以應該執行這樣的命令:
這就不會拿master分枝上最後一個快照和dev分枝上最後一個快照進行比對--而是用dev與master所交的那個分歧點和現在的dev分枝上最後一個快照進行比對。在我們這個例子中,這樣比對的結果是顯示對那個文件添加了一個函數。如果你目前正處在master分枝上,你可以運行:
跟上面的結果是一樣的。所以,如果你想查看將要合併的某個分枝會有什麼樣的變化,可以執行:
將branch替換爲你想要合併的分枝名即可。
$ git diff master dev
結果會顯示你給某個文件中添加了方法,還往README文件添加了一行內容。爲什麼會這樣?因爲對'dev'分枝來說,README文件還是原樣,而在'master'上,你已經刪掉了一行,這樣直接對兩個快照進行對比就好似'dev'分枝添加了一行進去一樣。你想查看的實際上是在創建dev分枝之後在這條分枝上的差異對比,所以應該執行這樣的命令:
$ git diff master...dev
這就不會拿master分枝上最後一個快照和dev分枝上最後一個快照進行比對--而是用dev與master所交的那個分歧點和現在的dev分枝上最後一個快照進行比對。在我們這個例子中,這樣比對的結果是顯示對那個文件添加了一個函數。如果你目前正處在master分枝上,你可以運行:
$ git diff ...dev
跟上面的結果是一樣的。所以,如果你想查看將要合併的某個分枝會有什麼樣的變化,可以執行:
$ git diff ...(branch)
將branch替換爲你想要合併的分枝名即可。