Mam ten sam problem i wpadł aliasu że wystarczyły (używam 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') #"
Jak używać:
difftoolr commit1..commit2 -M
(patrz na dole po więcej przykładów)
Jak to działa:
Wyobraź sobie, że masz trzy pliki, których nazwa została zmieniona. Jeden z nich rzeczywiście się zmienił (więc chcesz go sprawdzić za pomocą twojego difftoola), ale pozostałe dwa są identyczne, z wyjątkiem ścieżki lub nazwy (i chcesz je zignorować).
(different) path/file.old -> newPath/file.new
(identical) path/fileB.old -> newPath/fileB.new
(identical) path/fileC.old -> newPath/fileC.new
Co alias nie generuje specyfikacje ścieżkę, która wyraźnie wykluczyć fileB
i fileC
, to znaczy te pliki, które pomimo zmiany nazwy mają zawartość niezmienione.
Innymi słowy mamy do generowania tych filespecs:
-- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new
Zawiadomienie (chyba najtrudniejsza) części: stare ścieżki pliku i nowa ścieżka pliku musi być zarówno wyraźnie wyłączone.
Aby to zrobić, możemy wydać git diff
z następującymi wytycznymi:
-M100%
: wykonaj Zmienia nazwę. Co oznacza, że git zakłada, że dokonano jakiejś zmiany nazwy i uwzględni te informacje, aby dokonać porównań parami. Próg wynosi 100%, co nakazuje git rozważenie przemianowania tych plików, które mają dokładnie tę samą treść, ale nie te, które zostały zmienione.
--diff-filter=R
: wyświetla tylko te pliki, które git uważa za zmienione, pomijając pozostałe.
--names-only
: po prostu wypisz nazwy plików, nie ma innych informacji
-R
: Odwróć. W jednym kawałku skryptu zamieniamy kolejność porównywania (rodzaj przełączania lewej i prawej strony), więc wypisze również stare nazwy plików. Na przykład dyrektywa -R
wymienia plik newPath/fileB.new
jako path/fileB.old
.
...sed...
: i na końcu dołączamy dyrektywę wykluczającą :(exclude)
na początek wszystkich nazw plików.
Aby zająć się innymi przypadkami, utworzyłem trzy różne aliasy (niezbyt eleganckie, chciałbym coś bardziej elastycznego), aby można było użyć do określenia różnych rodzajów porównania.
git difftoolr0 -M
git difftoolr1 HEAD~1..HEAD -M
git difftoolr2 HEAD --cached -M
We wszystkich przypadkach „boki” (porównań zobowiązuje, --cached lub cokolwiek) musi być określona jako pierwszy parametr (y). Na przykład git difftoolr2 -M HEAD --cached
nie będzie działać (ponieważ najpierw pojawia się -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') #"
Wreszcie, BeyondCompare może również odpowiadać twoim potrzebom (i moim).
Pozwala to łatwo zmienić różnicę na "niestrukturalne".
Ta ostatnia usuwa foldery i pozostawia tylko imiona. Jeśli nazwa pliku jest taka sama (ale ścieżki mogą się różnić), są one traktowane jako dwie wersje tego samego pliku (na przykład path/file.png
i newPath/file.png
). W takim przypadku, jeśli zawartość nie uległa zmianie, można je łatwo pominąć za pomocą przycisku na górnym pasku.
W przypadku wystąpienia konfliktów "nazywania" (kilka plików po tej samej stronie porównania ma tę samą nazwę, pod różnymi ścieżkami), wybrałaby jedną z nich do porównania i zignorowała pozostałe.