Podświetl zmienione linie i zmienione bajty w każdej zmienionej linii

94

Projekt Open Source Trac ma doskonałe wyróżnienie różnic - podświetla zmienione linie i zmienione bajty w każdej zmienionej linii! Przykłady można znaleźć tutaj lub tutaj .

Czy istnieje sposób na użycie tego samego koloru podświetlenia (tj. Zmienionych linii i zmienionych bajtów ) w terminalu bash git, lub vim dla wyjścia różnicowego (plik łatki)?

Nikolay Frantsev
źródło
Co chcesz podkreślić? Czy potrzebujesz narzędzia porównującego, które podkreśla zmiany bajtów? (to byłoby bardzo pomocne). Mówisz vim, pamiętam, że vim dokonuje wielu operacji na kolorach już wtedy, gdy używasz szablonów języków programowania (i innych). Jak byś to zmienił? Dostępnych jest kilka technik zmiany koloru w oknie terminala, które jest zdefiniowane jako VT100 (i są dziesiątki innych definicji, które również obsługują sekwencje ucieczki kolorów). Więcej szczegółów proszę. Lub przeczytaj en.wikipedia.org/wiki/VT100 i powiązane linki. Może to pomoże.
łowca
Wiem, że interesują Cię tylko narzędzia open source i tylko terminal. Ale jako punkt odniesienia możesz spojrzeć na diffzilla slickedit. z kilku narzędzi porównywania, których użyłem, zawsze wydawał się najlepiej reprezentować różnice w znakach (chociaż z pewnością miał problemy, gdy różnice były złożone (połączenie formatowania i zmian kodu, co zawsze jest złym pomysłem)
nhed
Wygląda na dupę stackoverflow.com/questions/3231759/ ...
Adam Monsen
Uwaga: GitHub oferuje teraz takie narzędzie porównywania w swoim internetowym interfejsie graficznym: stackoverflow.com/a/25723584/6309
VonC
Opublikowałem „jeszcze jedno” czyste rozwiązanie oparte na git, diff-highlight z samouczkami, aby 1) znaleźć odpowiedni plik diff-highlight, 2) uczynić go wykonywalnym 3) ustawić niezbędne parametry w .gitconfig. Proszę spojrzeć. Instrukcje dotyczą Ubuntu 18.04, ale powinny działać ogólnie w systemach Linux.
Zorglub29

Odpowiedzi:

60

diff-highlightSkrypt Perl contrib produkuje wyjście tak podobna do screenów Trac, że jest prawdopodobne, że Trac używa go:

wprowadź opis obrazu tutaj

Zainstaluj za pomocą:

wget https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight && chmod +x diff-highlight

Przenieś plik diff-highlightdo ~/bin/katalogu (lub gdziekolwiek jesteś $PATH), a następnie dodaj następujące elementy do ~/.gitconfig:

[pager]
        diff = diff-highlight | less
        log = diff-highlight | less
        show = diff-highlight | less

Pojedyncza kopia wklej sugerowana przez @cirosantilli:

cd ~/bin
curl -O https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight
chmod +x diff-highlight
git config --global pager.log 'diff-highlight | less'
git config --global pager.show 'diff-highlight | less'
git config --global pager.diff 'diff-highlight | less'
git config --global interactive.diffFilter diff-highlight
Sina Samavati
źródło
To. To jest doskonałe. Dziękuję Ci. Wydaje się jednak, że w niektórych miejscach jest nieco konserwatywny, brakuje niektórych wierszy, które oczywiście mają większość tekstu wspólnego. Czy masz do tego narzędzie do śledzenia błędów?
naught101
21
Ach, to jest teraz część core git: github.com/git/git/tree/master/contrib/diff-highlight
naught101
2
Został teraz przekształcony w moduł i myślę, że najłatwiejszą wersją do pobrania jest ta bezpośrednio przed tą zmianą na raw.githubusercontent.com/git/git/ ...
Chris Midgley
4
Ta część core git jest nie tylko rozpowszechniana z gitem i prawdopodobnie już w Twoim systemie. W mojej odpowiedzi dodałem szczegóły, jak to włączyć. ↓
Cory Klein
2
To pomija różnice, które widzisz za pośrednictwem git add -p. Proszę również dodać:git config --global interactive.diffFilter diff-highlight
josch
41

Używając git difflub git logi być może innych, użyj opcji --word-diff=color(przy okazji są też inne tryby dla różnic między słowami)

anydot
źródło
2
--word-diff=colorjest naprawdę lepszy (zwłaszcza z git config color.diff.old "red reverse"i git config color.diff.new "green reverse"), ale nie tego chcę :(
Nikolay Frantsev
4
Więc jedyne, czego ci brakuje, to zaznaczanie kolorem / w jakiś sposób zarówno zmienione linie, jak i bajty w tym samym czasie?
anydot
7
Chcę podświetlić zmienione linie i zmienione bajty w każdej zmienionej linii, jak w Trac. Nie tylko zmienione bajty, to nie to samo.
Nikolay Frantsev
Możesz również użyć tego z git add --patch: stackoverflow.com/questions/10873882/ ...
naught101
Zaletą programu diff-highlightjest to, że działa dobrze zarówno w przypadku różnic między słowami, jak i wierszami.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
21

diff-so-fancyto diffrozświetlacz przeznaczony do ludzkich gałek ocznych.

Usuwa początkowe +/, -które są irytujące przy wycinaniu / wklejaniu i zapewnia wyraźne sekcje między plikami.

Kolorowe git(po lewej) vs diff-so-fancy(po prawej - zwróć uwagę na wyróżnienia na poziomie postaci):

diff-so-fancy wyjście

Jeśli chcesz, aby diff-so-fancywyjście (po prawej stronie) nie było ograniczone do plików w gitrepozytorium, dodaj następującą funkcję do swojej, .bashrcaby użyć jej na dowolnych plikach:

dsf() { git diff --no-index --color "$@" | diff-so-fancy; }

Na przykład:

dsf original changed-file

Podświetlanie poziomu postaci i standardowy diffformat

Jeśli nie podoba ci się niestandardowe formatowanie diff-so-fancy, ale nadal chcesz gitpodświetlać na poziomie znaków , użyj tego, diff-highlightco weźmie gitdane wyjściowe i utworzy naprawdę całkiem standardowe diffwyjście w formacie:

zrzut ekranu diff-highlight

Aby używać go domyślnie z dnia git, dodaj do .gitconfig:

[color "diff-highlight"]
  oldNormal = red bold
  oldHighlight = red bold 52
  newNormal = green bold
  newHighlight = green bold 22

[pager]
  diff = diff-highlight | less -FRXsu --tabs=4

[pager]Odcinek opowiada gitzamontowanie jej już colourised wyjście do diff-highlightktórego colourises na poziomie znaków, a następnie strony wyjście na mniej (w razie potrzeby), a nie tylko przy użyciu domyślnego less.

Tom Hale
źródło
To bardzo interesujące, czy mógłbyś trochę wyjaśnić te gitconfigopcje?
Caesarsol
Zaktualizowano, dodano również funkcję dsf().
Tom Hale,
15

Zachowanie, które chcesz, jest teraz dostępne w samym git (jak wskazano w komentarzu nigt101). Aby to włączyć, musisz ustawić pager na

perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

gdzie /usr/share/doc/git/contrib/diff-highlight/diff-highlightjest lokalizacja skryptu wyróżniającego na Ubuntu 13.10 (nie mam pojęcia, dlaczego znajduje się w docfolderze). Jeśli nie ma go w twoim systemie, spróbuj locate diff-highlightgo znaleźć. Zauważ, że skrypt podświetlania nie jest wykonywalny (przynajmniej na moim komputerze), stąd wymóg perl.

Aby zawsze używać zakreślacza dla różnych poleceń podobnych do różnic, po prostu dodaj do ~/.gitconfigpliku:

[pager]
    log = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    show = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    diff = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

Dodałem to jako nowa odpowiedź, komentarz nict101 jest zakopany, a ponieważ konfiguracja nie jest tak banalna, jak powinna, i przynajmniej w wersji Ubuntu, że mam instrukcje w pliku README nie działają.

dshepherd
źródło
Właśnie zauważyłem, że nie włącza to podświetlania różnic w obrębie git add -p(tryb interaktywny). Nie wiem jednak, jak można to naprawić, po prostu dodanie add do listy powoduje zawieszenie się.
dshepherd
5
To powinno teraz działać w git 2.9.0:git config interactive.diffFilter diff-highlight
Thomas
^ To! Niestety diff-highlightnie był na mojej drodze, więc musiałem go najpierw zlokalizować. Szczegóły w mojej odpowiedzi poniżej.
Cory Klein
11

Narzędzie do różnic opartych na bajtach jest dystrybuowane z oficjalnym Gitem od wersji 1.7.8 1 . Musisz tylko zlokalizować, gdzie jest zainstalowany na twoim komputerze i włączyć go.

Dowiedz się, gdzie jest zainstalowany Git

  • MacOS z Git zainstalowanym przez Homebrew : To/usr/local/opt/git
  • Windows z Git dla Windows : Uruchom, cd / && pwd -Waby znaleźć katalog instalacyjny.
  • Linux: Nerd. Jeśli jeszcze nie wiesz, gdzie jest zainstalowany Git, to ll $(which git)lub locate gitpowinieneś pomóc.

Połącz diff-highlightz katalogiem bin, aby ścieżka PATH mogła go znaleźć

GIT_HOME='/usr/local/opt/git/'  # Use the value from the first step.
ln -s "${GIT_HOME}/share/git-core/contrib/diff-highlight/diff-highlight" \
      '/usr/local/bin/diff-highlight'

Włącz to w konfiguracji Git

git config --global interactive.diffFilter diff-highlight # Use on interactive prompts
git config --global pager.diff "diff-highlight | less"    # Use on git diff
git config --global pager.log  "diff-highlight | less"    # Use on git log
git config --global pager.show "diff-highlight | less"    # Use on git show

1 Oto wersja 1.7.8 , ale od tamtej pory wprowadzono wiele zmian .

Cory Klein
źródło
1
Dobrze byłoby sprecyzować, w jakiej wersji zaczął być rozpowszechniany za pomocą gita. Zgaduję również, że dystrybucje domyślnie umieszczą go w PATH, więc krok dowiązania symbolicznego nie będzie potrzebny? I which gitwymaga, aby znajdował się w PATH w pierwszej kolejności, więc nie zadziała, jeśli nie jest :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
2
Dobrze byłoby! Zapraszam do dodania tych informacji. I chociaż Git robi to w pakiecie diff-highlight, w rzeczywistości go nie instaluje , więc krok dowiązania symbolicznego jest rzeczywiście konieczny (przynajmniej w systemie MacOS). Jeśli uznasz, że nie jest to konieczne dla Twojej platformy, ponownie możesz zaktualizować odpowiedź. Tymczasem which gitzwykle działa, ponieważ Git robi zainstalować gitbinarną gdzieś na drodze.
Cory Klein
Zauważ, że w debian unstable musiałem "skompilować" ten plik, ponieważ miałem właśnie rozszerzenie .perl. Kompilacja jest banalna: wystarczy uruchomić ją sudo makew diff-highlightkatalogu.
tobiasBora
10

Używam --color-wordsopcji i u mnie działa dobrze:

$ git diff --color-words | less -RS
amized
źródło
5
Nie, to tylko pokazuje różnicę w słowach. To, czego chce OP (i ja), to normalna różnica wiersz po wierszu, z podświetlonymi różnicami w słowach (więc powiedzmy, że różne wiersze są kolorowym tekstem, a różnice w wyrazach w tych wierszach to normalny kolorowy tekst z kolorowym podświetleniem lub coś). Zobacz przykładowe linki teraz w pytaniu.
naught101
1
pastebin.com/1JrhYHRt Właściwie używam vimdiff jako difftool i vimdiff ze schematem kolorów molokai, aby uzyskać ładne podkreślenie, jak opisujesz w swoim pytaniu. 1- git config --global diff.tool vimdiff 2- in vim ": colo molokai" * Molokai @ github.com/tomasr/molokai * Możliwy automatyczny schemat kolorów z ~ / .vimrc: if & diff ustaw tło = ciemne kolory molokai endif
amized
4

jak mówi @dshepherd :

Zachowanie, które chcesz, jest teraz dostępne w samym git

Ale diff-highlightznajduje się w DOC i nie jest dostępny z powłoki.
Aby zainstalować diff-highlightw swoim ~/binkatalogu, wykonaj następujące kroki (pozwoli to zaoszczędzić wpisywanie):

$ locate diff-highlight
$ cd /usr/share/doc/git/contrib/diff-highlight  #or path you locate
$ sudo make
$ mv diff-highlight ~/bin

Następnie skonfiguruj swój .gitconfigzgodnie z oficjalnym dokumentem:

[pager]
    log  = diff-highlight | less
    show = diff-highlight | less
    diff = diff-highlight | less

UPD
Możesz także wypróbować następny najnowszy gitbez żadnej instalacji:

git diff --color-words=.

Bardziej złożony:

git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Eugen Konkov
źródło
1

Emacs posiada funkcję ediff-patch-buffer, która powinna spełnić Twoje potrzeby.

Otwórz nienaprawiony plik w emacsie typu ESC-x, ediff-patch-buffer.

Postępuj zgodnie z wyświetlanymi instrukcjami, a powinieneś zobaczyć podświetlone porównanie poprawionej i oryginalnej wersji pliku.

Zgodnie z Twoim komentarzem, poniżej znajdziesz rozwiązanie bash wymagające tylko dwdiff:

#!/bin/bash
paste -d'\n' <(dwdiff -2 -L -c <(cat $2) <(patch $2 -i $1 -o -)) <(dwdiff -1 -L -c <(cat $2) <(patch $2 -i $1 -o -))| uniq
Finbar Crago
źródło
Przepraszam, ale nie chcę emacs użytku, tylko bash, Git lub vim
Nikolay Frantsev
To zrozumiałe. Jedyne co mogę myśleć jest użycie colordiff z stdout z patchem: colordiff -u <(patch original_file -i patch_file -o -) <(cat original_file) ale to będzie tylko podkreślić linie zmieniły nie gryzie ...
Finbar Crago
Dokładniej przemyślałem Twój problem i dołączyłem drugie rozwiązanie, które wymaga tylko dwdiff.
Finbar Crago
1
przeczytaj uważnie moje pytanie, nie chcę porównywać plików
Nikolay Frantsev
1
przepraszam za zamieszanie, więc po prostu szukasz sposobu na wyróżnienie zmienionych bajtów w zmienionych wierszach pliku różnicowego? jeśli tak, spróbujdwdiff -c --diff-input diff_file
Finbar Crago
1

Diffy

GitLab używa Diffy https://github.com/samg/diffy (Ruby), aby uzyskać wyniki podobne do GitHub i diff-highlight:

wprowadź opis obrazu tutaj

Diffy sam tworzy różnicę, używając tego samego algorytmu, co Git i obsługuje różne typy danych wyjściowych, w tym dane wyjściowe HTML używane przez GitLab:

gem install diffy
echo '
  require "diffy"    
  puts Diffy::Diff.new("a b c\n", "a B c\n").to_s(:html)
' | ruby

Wynik:

<div class="diff">
  <ul>
    <li class="del"><del>a <strong>b</strong> c</del></li>
    <li class="ins"><ins>a <strong>B</strong> c</ins></li>
  </ul>
</div>

Zwróć uwagę, jak strongzostało dodane do zmienionych bajtów.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło
0

Tak, Vim robi to łącznie z podświetlaniem tekstu zmienionego w linii.
Zobacz :h diffi :h 08.7po więcej szczegółów na temat porównywania plików.

Vim używa dość prostego algorytmu do podświetlania. Przeszukuje wiersz pod kątem pierwszego zmienionego znaku, a następnie ostatniego zmienionego znaku i po prostu podświetla wszystkie znaki między nimi.
Oznacza to, że nie możesz mieć wielu wyróżnień na linię - wiele decyzji projektowych w Vimie nadaje priorytet wydajności.

PDug
źródło
niestety nie podświetla zmienionych bajtów na wyjściu diff (set filetype = diff)
Nikolay Frantsev
1
Myślę, że teraz rozumiem twoje pytanie - chcesz podświetlić składnię tekstową wyjście polecenia diff, tak aby podświetlało wszelkie zmiany wprowadzone w linii. Edycja tego tekstu w Vimie podkreśla różnice między liniami, ale nie zmiany wprowadzone w linii.
PDug
Czy mógłbyś użyć polecenia Vima: patchfile, aby załadować oryginalny plik, a następnie porównać go z poprawioną wersją?
PDug
niestety nie, chcę użyć rekurencyjnego wyjścia diff dla wielu plików
Nikolay Frantsev
0

vimdiff file1 file2 wyświetli różnicę znakową między dwoma plikami.

vimdiff jest narzędziem porównywania zawartym w vimie. (Vim powinien być skompilowany z opcją + diff, aby mieć pewność, że możesz to sprawdzić :version)

Możesz również uruchomić go z wnętrza vima. Zobacz, :help diffaby uzyskać więcej informacji i poleceń.

Xavier T.
źródło
Nie chcę porównywać plików, chcę podświetlić plik diff (łatka).
Nikolay Frantsev
@Nikolay Frantsev Jeśli nie zależy Ci na wydajności, możesz zainstalować moją wtyczkę format.vim i zrobić vimdiff file.old file.new -c 'FormatCommand diffformat' -c 'w! file.diff.html' -c 'qa!'.
ZyX
Spowoduje to zrobienie różnicy w trybie wsadowym ( screen -D -mdołączenie z wyprzedzeniem lub dopisanie &>/dev/null(wariant / dev / null czasami powoduje dziwne błędy), jeśli nie chcesz widzieć flashowania terminala) i wyjdzie z vima po zakończeniu formatowania, ale jest to czysty vimscript i nawet z moimi optymalizacjami jest bardzo powolny dla dużych plików.
ZyX
0

Uwaga : to jest duplikat tego, co znajduje się tutaj: Jak poprawić podświetlanie różnic w git? . Jednak zamieszczam tutaj również moją odpowiedź, ponieważ może to być pomocne dla niektórych osób, które bezpośrednio znajdą ten wątek :)

Jak powiedziano w niektórych poprzednich odpowiedziach, jest to możliwe tylko w przypadku rzeczy git. Publikuję to, ponieważ instrukcje mogą być nieco łatwiejsze do wykonania w zależności od twojego systemu, ale jest to podobne do kilku innych odpowiedzi.

Jedno rozwiązanie, które opiera się wyłącznie na git i jego wkładach. Nie wymaga to dodatkowych plików niż te, które są dostarczane z git . Wszystkie wyjaśnienia dotyczą Ubuntu (testowane na 18.04LTS), powinny działać podobnie na innych systemach linuxowych:

  • Znajdź fragment kodu git contrib w diff-highlight:
find -L /usr -name diff-highlight -type f

w moim systemie jedyną poprawną odpowiedzią jest:

/usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Spraw, aby odpowiedni skrypt Perla był wykonywalny. W moim przypadku musiałem zrobić:
sudo chmod +x /usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Zaktualizuj swój, ~/.gitconfigaby uzyskać pożądany wynik, dodając (pamiętaj, że są to TABS, a nie 4 spacje):
[color "diff-highlight"]
    oldNormal = red
    oldHighlight = red 52
    newNormal = green
    newHighlight = green 22
  • Ciesz się wynikiem (uwaga: dotyczy to tylko kolorowania różnicowego + podświetlenia, mam tu też inne rzeczy do zrobienia, oczywiście :)).

diff-highligh

Zorglub29
źródło