2016-02-12 81 views
6

我使用:git的差異改名/移動文件和修改文件但跳過重命名/移動和完全相同的文件

git diff HEAD --diff-filter=R -M 

與合併外部diff工具顯示已更名兩者/移動的和修改過的文件。在做提交之前,我總是先做一個git diff來檢查我的工作並正確地組裝提交消息。很多時候我會重命名/移動文件,這些文件還需要在引用一些重命名/移動文件的文件中進行一些路徑更改。

我的問題是,爲了顯示已重命名並修改過的文件的差異,git diff還彈出了一堆已重命名但未修改的文件的合併窗口。這可能非常煩人。如何讓git diff跳過重命名但未修改的文件?當我以更簡潔的方式輸入git狀態時,我將看到列出的所有文件被重命名/移動,因此我不希望使用git diff的相同文件彈出窗口。

回答

1

我有同樣的問題,並想出了一個別名奏效了(我使用Git 2.8.3)

[alias] 
    difftoolr = "!git difftool \"[email protected]\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" 

使用方法:

difftoolr commit1..commit2 -M 

(見底部有更多的例子)

工作原理:

想象一下,您有三個已重命名的文件。其中一個實際上已經改變了它的內容(所以你想用difftool來檢查它),但其他兩個是相同的,除了路徑或名稱(並且你想忽略它們)。

(different) path/file.old -> newPath/file.new 
(identical) path/fileB.old -> newPath/fileB.new 
(identical) path/fileC.old -> newPath/fileC.new 

什麼別名也正在生成路徑規範,明確排除fileBfileC,即這些文件,儘管重命名有內容不變。
換句話說,我們正在生成這些filespecs:

-- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new 

通知的(也許是最棘手的)部分:舊的文件路徑和新的文件路徑必須是明確排除。

要做到這一點,我們發出以下指令一個git diff

  • -M100%:按照重命名。這意味着git是假設一些重命名已完成,並將考慮這個信息做成對比較。閾值是100%,它指示git考慮重新命名具有完全相同內容的文件,但不是那些被更改的文件。
  • --diff-filter=R:僅列出git考慮重命名的文件,省略其他文件。
  • --names-only:只輸出文件名,沒有其他信息
  • -R:反向。在腳本的一部分中,我們交換了比較順序(左右切換的順序),因此它也會輸出舊的文件名。例如,-R指令將文件newPath/fileB.new列爲path/fileB.old
  • ...sed...:最後我們排除指令:(exclude)追加到所有文件名的開頭。

爲了處理其他情況,我創建了三個不同的別名(不是很優雅,我想要更靈活的東西),所以它可以用來指定不同類型的比較。

git difftoolr0 -M 
git difftoolr1 HEAD~1..HEAD -M 
git difftoolr2 HEAD --cached -M 

在所有情況下,「比較的兩邊」(提交, - 緩存或其他)必須被指定爲第一個參數。例如git difftoolr2 -M HEAD --cached將不起作用(因爲-M首先出現)。

[alias] 
# takes no parameter: sample usage: git difftoolr0 -M 
difftoolr0 = "!git difftool \"[email protected]\" -- . $((git diff -M100% --diff-filter=R --name-only & git diff -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" 

# takes 1 parameter in first position: sample usage: git difftoolr1 HEAD~1..HEAD -M 
difftoolr1 = "!git difftool \"[email protected]\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" 

# takes 2 parameters in first positions: sample usage: git difftoolr2 HEAD --cached -M 
difftoolr2 = "!git difftool \"[email protected]\" -- . $((git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only & git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #" 

最後,BeyondCompare可能也適合您的需求(和我的)。
它可以輕鬆地將並排diff切換爲「非結構化」diff。

關閉文件夾後者條,只保留了名字。如果文件名相同(但路徑可能不同),則它們被視爲同一文件的兩個版本(例如path/file.pngnewPath/file.png)。在這種情況下,如果內容沒有改變,可以使用上面的一個按鈕輕鬆省略。

如果「命名」衝突發生時(比較的同一側的幾個文件具有相同的名稱,在不同的路徑),它會選擇比較他們的只有一個,而忽略其他。

相關問題