Jak mogę uzyskać różnicę obok siebie, kiedy wykonuję „git diff”?


163

Kiedy piszę „git diff”, chciałbym zobaczyć różnicę obok siebie, na przykład „diff -y”, lub wyświetlić różnicę w interaktywnym narzędziu porównywania, takim jak „kdiff3”. Jak to zrobić?




Odpowiedzi:


89

Chociaż Git ma wewnętrzną implementację diff, możesz zamiast tego skonfigurować zewnętrzne narzędzie.

Istnieją dwa różne sposoby określenia zewnętrznego narzędzia porównywania:

  1. ustawienie GIT_EXTERNAL_DIFFi GIT_DIFF_OPTSzmienne środowiskowe.
  2. konfigurowanie zewnętrznego narzędzia porównywania za pośrednictwem git config

Zobacz też:

Wykonując a git diff, Git sprawdza zarówno ustawienia powyższych zmiennych środowiskowych, jak i .gitconfigplik.

Domyślnie Git przekazuje następujące siedem argumentów do programu porównującego:

path  old-file  old-hex old-mode  new-file  new-hex new-mode

Zwykle potrzebujesz tylko parametrów starego i nowego pliku. Oczywiście większość narzędzi porównujących przyjmuje tylko dwie nazwy plików jako argumenty. Oznacza to, że musisz napisać mały skrypt opakowujący, który pobierze argumenty, które Git dostarcza do skryptu i przekaże je zewnętrznemu programowi git, który wybierzesz.

Powiedzmy, że umieściłeś swój skrypt opakowujący pod ~/scripts/my_diff.sh:

#!/bin/bash
# un-comment one diff tool you'd like to use

# side-by-side diff with custom options:
# /usr/bin/sdiff -w200 -l "$2" "$5" 

# using kdiff3 as the side-by-side diff:
# /usr/bin/kdiff3 "$2" "$5"

# using Meld 
/usr/bin/meld "$2" "$5"

# using VIM
# /usr/bin/vim -d "$2" "$5"

następnie musisz uczynić ten skrypt wykonywalnym:

chmod a+x ~/scripts/my_diff.sh

Następnie musisz powiedzieć Gitowi, jak i gdzie znaleźć niestandardowy skrypt opakowujący różnice. Masz trzy możliwości, jak to zrobić: (wolę edytować plik .gitconfig)

  1. Korzystanie GIT_EXTERNAL_DIFF,GIT_DIFF_OPTS

    np. w swoim pliku .bashrc lub .bash_profile możesz ustawić:

    GIT_EXTERNAL_DIFF=$HOME/scripts/my_diff.sh
    export GIT_EXTERNAL_DIFF
    
  2. Za pomocą git config

    użyj „git config”, aby określić, gdzie można znaleźć twój skrypt opakowujący:

    git config --global diff.external ~/scripts/my_diff.sh
    
  3. Edycja ~/.gitconfigpliku

    możesz edytować ~/.gitconfigplik, aby dodać następujące wiersze:

    [diff]
      external = ~/scripts/my_diff.sh
    

Uwaga:

Podobnie jak w przypadku instalowania niestandardowego narzędzia porównywania, możesz również zainstalować niestandardowe narzędzie do scalania, które może być wizualnym narzędziem do scalania, aby lepiej pomóc w wizualizacji scalania. (patrz strona progit.org)

Zobacz: http://fredpalma.com/518/visual-diff-and-merge-tool/ i https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration


1
Czy to zachowuje kolorystykę terminala git?
Sridhar Sarnobat

3
To jest świetne, ale uruchamia nową przeglądarkę dla każdego pliku. Jakiś sposób na utworzenie skonsolidowanej różnicy w, powiedzmy meld,?
HRJ

2
@Tilo Otrzymuję błąd dla vima jako im: Ostrzeżenie: Wyjście nie jest na terminalu
martwy programista

Czy meldwersję można skonfigurować tak, aby wykonywała porównywanie katalogu, w którym mogę wybrać plik (i), dla których chcę zobaczyć różnicę? Obecnie uruchamia osobne meldpolecenie dla każdego pliku i muszę wyjść meld, aby zobaczyć następny plik. Wolałbym raczej meldpokazać listę katalogów zmienionych plików, tak jak zachowuje się, gdy meldjest używany z Mercurial.
kasperd

163

Spróbuj git difftool

Użyj git difftoolzamiast git diff. Nigdy nie wrócisz.

UPDATE, aby dodać przykładowe użycie:

Oto link do innego stosu, który mówi o git difftool: Jak wyświetlić wynik „git diff” za pomocą mojego preferowanego narzędzia / przeglądarki porównywania?

Nowsze wersje gitThe difftoolkomenda obsługuje wiele zewnętrznych narzędzi diff out-of-the-box. Na przykład vimdiffjest obsługiwany automatycznie i można go otworzyć z wiersza poleceń przez:

cd /path/to/git/repo
git difftool --tool=vimdiff

Inne obsługiwane zewnętrzne narzędzia porównujące są wymienione w poniższym git difftool --tool-helpprzykładzie:

'git difftool --tool=<tool>' may be set to one of the following:
        araxis
        kompare
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        bc3
        codecompare
        deltawalker
        diffuse
        ecmerge
        emerge
        gvimdiff
        gvimdiff2
        kdiff3
        meld
        opendiff
        tkdiff
        xxdiff

34
A może wrócisz, jeśli dostaniesz This message is displayed because 'diff.tool' is not configured.. Być może zaktualizuj odpowiedź z minimalną konfiguracją tego elementu, aby wyświetlała obok siebie różnice w terminalu, o co prosił OP? Narzędzia GUI są zupełnie bezużyteczne na zdalnym serwerze, na którym łączysz się za pomocą ssh.
Petr

1
Interesująca uwaga, chociaż nie sądzę, żebym osobiście kiedykolwiek potrzebował używać gita podczas SSH. Jedną z fajnych rzeczy w DVCS jest część rozproszona: przynajmniej w moich środowiskach nigdy nie jest kłopotliwe lokalne klonowanie repozytorium, które chcę przeglądać.
Matt Ball

1
Przynajmniej w mojej konfiguracji, git difftoolz vimdiffnie zawsze ustawia poprawnie dwa pliki / bufory.
Rohmer

1
To miłe, a więc poniżej na liście odpowiedzi: O Używam, git difftool -yaby zapobiec podpowiedziom tkdiff
harshvchawla

Powiązane: Make meld your git difftoolin Windows i Linux: stackoverflow.com/a/48979939/4561887
Gabriel Staples

55

Możesz też spróbować git diff --word-diff. To nie jest dokładnie obok siebie, ale w jakiś sposób lepsze, więc możesz preferować to od rzeczywistych potrzeb.


12
To najłatwiejszy sposób. Jeszcze lepsze jestgit diff --word-diff=color
Rolf

@Rolf --word-diff=colordaje mi błąd nieprawidłowej opcji. W której wersji został wprowadzony?
Holloway

@Trengot Uruchamiam git 1.7.9, który pochodzi z 02/2012
Rolf

4
Domyślnie zainstalowana wersja @Rolfa to 1.7.1. Mógłby wyjaśnić różnicę. git diff --color-wordsdziała.
Holloway

4
Tak, git diff --color-wordsto sposób na przejście na nowoczesne wersje gita.
VasiliNovikov

41

ydiff

Dawniej nazywane cdiff, to narzędzie może wyświetlić obok siebie , przyrostem i kolorowe diff.

Zamiast git diffrobić:

ydiff -s -w0

Spowoduje to uruchomienie ydiffw trybie wyświetlania obok siebie dla każdego z plików z różnicami.

Zainstaluj za pomocą:

python3 -m pip install --user ydiff

-lub-

brew install ydiff

Dla git log, można użyć:

ydiff -ls -w0

-w0automatycznie wykrywa szerokość terminala. Zobacz ydiff stronę repozytorium GitHub, aby uzyskać szczegółowe informacje i wersję demonstracyjną.

Testowane w Git 2.18.0, ydiff 1.1.


@RyneEverett: Czy możesz wyjaśnić, jak zrobić odpowiednik git diff | cdiff -sz icdiff?
einpoklum

Po prostu uruchom ydiff -sz obszaru roboczego git / svn / hg, nie musisz się
łączyć

jeśli chcesz ograniczyć różnicę do określonego pliku w historii Gita, cd <git repo>a następnie uruchomićydiff -ls <path/to/file>
slm

22

Możesz zrobić to obok siebie, diffużywając sdiff:

$ git difftool -y -x sdiff  HEAD^ | less

gdzie HEAD^jest przykład, który powinieneś zastąpić czymkolwiek chcesz porównać.

Znalazłem to rozwiązanie tutaj, gdzie jest też kilka innych sugestii. Jednak ta jedna odpowiedź jest zwięzła i jasna na pytanie PO.

Zobacz man git-difftool po wyjaśnienie argumentów.


Biorąc pod uwagę komentarze, możesz utworzyć przydatne git sdiffpolecenie, pisząc następujący skrypt wykonywalny:

#!/bin/sh
git difftool -y -x "sdiff -w $(tput cols)" "${@}" | less

Zapisz to jako /usr/bin/git-sdiffi chmod -xto. Wtedy będziesz mógł to zrobić:

$ git sdiff HEAD^

Zwykle robię "$ git difftool -x 'sdiff -s -w 240'" (lub jakąkolwiek szerokość ekranu), jeśli / kiedy chcę ukryć te same linie i jest tylko jeden plik (w przeciwnym razie robię vimdiff)
HidekiAI

1
@HidekiAI Uważam to ból wpisać szerokość terminala za każdym razem, więc mogę używać tput colszamiast, na przykład: git difftool -x "sdiff -s -w $(tput cols)".
jaume

czy może uwydatnić zmiany koloru? W tej chwili wydaje się, że musimy użyć naszych oczu, aby dostrzec, jakie właściwie są zmiany
nonopolarity

Zamień sdiff na icdiff, aby uzyskać ładny kolorowy wyświetlacz.
Greg

10
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

to po prostu:

git diff

1
`meld. ' działa też! I pokazuje wszystkie zmiany w skonsolidowanym oknie.
HRJ

@HRJ, które działa idealnie! Tak proste i praktyczne :)
waldyrious

9

Jeśli chcesz zobaczyć równoległe różnice w przeglądarce bez angażowania GitHub, możesz cieszyć się git webdiff , zastępczym zamiennikiem dla git diff:

$ pip install webdiff
$ git webdiff

Oferuje to szereg zalet w porównaniu z tradycyjnymi narzędziami różnicowymi GUI, na przykład tkdiffpodświetlenie składni i wyświetlanie różnic w obrazach.

Przeczytaj więcej na ten temat tutaj .


7

Używam colordiff .

W systemie Mac OS X zainstaluj go z

$ sudo port install colordiff

W Linuksie jest prawdopodobnie apt get install colordifflub coś takiego, w zależności od twojej dystrybucji.

Następnie:

$ git difftool --extcmd="colordiff -ydw" HEAD^ HEAD

Lub utwórz alias

$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""

Wtedy możesz go użyć

$ git diffy HEAD^ HEAD

Nazwałem to „diffy”, ponieważ diff -yjest to różnica side-by-side w unixie. Colordiff dodaje też kolory, które są ładniejsze. W opcji -ydw, yjest side-by-strony, wjest ignorowanie spacje, a dto w celu uzyskania minimalnej diff (zwykle można dostać lepszy wynik jako diff)


dodaj, -yaby pominąć Launch 'colordiff' [Y/n]:monit.
Beni Cherniavsky-Paskin

czy na pewno tak jest git alias diffy "difftool --extcmd=\"colordiff -ydw\""? Nie powinno być git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\""?
nonopolarity

6

Dla unixa, łączenie samego giti wbudowanego diff:

git show HEAD:path/to/file | diff -y - path/to/file

Oczywiście możesz zamienić HEAD na dowolne inne odniesienie do gita i prawdopodobnie chcesz dodać coś podobnego -W 170do polecenia diff.

Zakłada się, że właśnie porównujesz zawartość katalogu z poprzednim zatwierdzeniem. Porównanie dwóch zatwierdzeń jest bardziej złożone. Jeśli twoja powłoka to bash, możesz użyć "podstawienia procesu":

diff -y -W 170 <(git show REF1:path/to/file) <(git show REF2:path/to/file)

gdzie REF1i REF2są referencjami git - tagami, gałęziami lub skrótami.


Dzięki - Twoje polecenie „git show HEAD: ścieżka / do / pliku” było tym, czego potrzebowałem, aby wymyślić własne rozwiązanie, „vimdfiff <(git show HEAD: ścieżka / do / pliku) ścieżka / do / pliku”. Bity nadal nie są ustawione poprawnie, ale to najlepsze rozwiązanie, jakie mam teraz.
talexb

5

Osobiście bardzo lubię icdiff !

Jeśli jesteś na Mac OS Xz HomeBrew, po prostu zrobić brew install icdiff.

Aby poprawnie uzyskać etykiety plików oraz inne fajne funkcje, mam w moim ~/.gitconfig:

[pager]
    difftool = true
[diff]
    tool = icdiff
[difftool "icdiff"]
    cmd = icdiff --head=5000 --highlight --line-numbers -L \"$BASE\" -L \"$REMOTE\" \"$LOCAL\" \"$REMOTE\"

I używam go tak: git difftool


3

To pytanie pojawiło się, gdy szukałem szybkiego sposobu wykorzystania wbudowanego sposobu git do lokalizowania różnic. Moje kryteria rozwiązania:

  • Szybki start, potrzebne wbudowane opcje
  • Z łatwością obsługuje wiele formatów, XML, różne języki programowania
  • Szybko identyfikuj małe zmiany kodu w dużych plikach tekstowych

Znalazłem tę odpowiedź, aby uzyskać kolor w git.

Aby uzyskać różnicę obok siebie zamiast różnic liniowych, poprawiłem doskonałą odpowiedź mb14 na to pytanie za pomocą następujących parametrów:

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]"

Jeśli nie podoba ci się dodatkowa [- lub {+] opcja --word-diff=colormoże zostać użyta.

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]" --word-diff=color

Pomogło to uzyskać prawidłowe porównanie z tekstem json i xml oraz kodem java.

Podsumowując, --word-diff-regexopcje mają pomocną widoczność wraz z ustawieniami kolorów, aby uzyskać pokolorowany obok siebie kod źródłowy w porównaniu do standardowego porównania linii, podczas przeglądania dużych plików z małymi zmianami linii.


3

Kilku innych wspomniało już o cdiff dla porównywania side-by-side przez git, ale nikt nie dał pełnej implementacji.

Konfiguracja cdiff:

git clone https://github.com/ymattw/cdiff.git
cd cdiff
ln -s `pwd`/cdiff ~/bin/cdiff
hash -r # refresh your PATH executable in bash (or 'rehash' if you use tcsh)
        # or just create a new terminal

Edytuj ~ / .gitconfig, wstawiając te linie:

[pager]
        diff = false
        show = false

[diff]
        tool = cdiff
        external = "cdiff -s $2 $5 #"

[difftool "cdiff"]
        cmd = cdiff -s \"$LOCAL\" \"$REMOTE\"

[alias]
        showw = show --ext-dif

Pager off jest potrzebny, aby cdiff działał z Diff, i tak jest to zasadniczo pager, więc jest w porządku. Difftool będzie działać niezależnie od tych ustawień.

Alias ​​show jest potrzebny, ponieważ git show obsługuje tylko zewnętrzne narzędzia porównujące poprzez argument.

Ważny jest znak „#” na końcu zewnętrznego polecenia diff. Polecenie diff Gita dołącza $ @ (wszystkie dostępne zmienne diff) do polecenia diff, ale chcemy tylko dwóch nazw plików. Więc wywołujemy te dwa wyraźnie za pomocą 2 $ i 5 $, a następnie ukrywamy $ @ za komentarzem, który w innym przypadku zmyliłby sdiff. Powoduje to błąd, który wygląda tak:

fatal: <FILENAME>: no such path in the working tree
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

Polecenia Git, które teraz generują porównywanie obok siebie:

git diff <SHA1> <SHA2> 
git difftool <SHA1> <SHA2>
git showw <SHA>

Użycie Cdiff:

'SPACEBAR' - Advances the page of the current file.
'Q'        - Quits current file, thus advancing you to the next file.

Masz teraz porównywanie side-by-side za pośrednictwem git diff i difftool. I masz kod źródłowy cdiff python do dostosowywania użytkownika, jeśli będziesz go potrzebować.


2

Oto podejście. Jeśli przepuścisz przez less, szerokość xterm jest ustawiona na 80, co nie jest takie gorące. Ale jeśli wykonasz polecenie np. COLS = 210, możesz wykorzystać rozszerzony xterm.

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}

1
Zabawny. Podpisałem się pseudonimem, ale to zostało zignorowane ... Dzięki za wypisanie się ze mnie, Stack Overflow. :(
Thomas Mellman

2

Otwórz Intellij IDEA , wybierz pojedyncze lub wiele zatwierdzeń w oknie narzędzia „Kontrola wersji”, przeglądaj zmienione pliki i kliknij je dwukrotnie, aby sprawdzić zmiany obok siebie dla każdego pliku.

Dzięki dołączonemu programowi uruchamiającemu wiersz poleceń możesz przenieść IDEA w dowolnym miejscu za pomocą prostego idea some/path

widok kontroli wersji widok różnic


1

W tym wątku jest wiele dobrych odpowiedzi. Moim rozwiązaniem tego problemu było napisanie scenariusza.

Nazwij to `` git-scriptname '' (i uczyń go wykonywalnym i umieść go w swojej PATH, jak każdy skrypt) i możesz wywołać go jak normalne polecenie git, uruchamiając

$ git scriptname

Rzeczywista funkcjonalność to tylko ostatnia linia. Oto źródło:

#!/usr/bin/env zsh
#
#   Show a side-by-side diff of a particular file how it currently exists between:
#       * the file system
#       * in HEAD (latest committed changes)

function usage() {
    cat <<-HERE
    USAGE

    $(basename $1) <file>

    Show a side-by-side diff of a particular file between the current versions:

        * on the file system (latest edited changes)
        * in HEAD (latest committed changes)

HERE
}

if [[ $# = 0 ]]; then
    usage $0
    exit
fi

file=$1
diff -y =(git show HEAD:$file) $file | pygmentize -g | less -R

1

To może być nieco ograniczone rozwiązanie, ale działa przy użyciu polecenia systemu diffbez zewnętrznych narzędzi:

diff -y  <(git show from-rev:the/file/path) <(git show to-rev:the/file/path)
  • filtruj tylko używane linie zmiany --suppress-common-lines(jeśli Twoja diffopcja obsługuje tę opcję).
  • brak kolorów w tym przypadku, tylko zwykłe diffmarkery
  • może dostosować szerokość kolumny --width=term-width; w Bash można uzyskać szerokość jako $COLUMNSlub tput cols.

Można to również umieścić w pomocniczym skrypcie git dla większej wygody, na przykład w następujący sposób:

git diffy the/file/path --from rev1 --to rev2
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.