Wyświetlaj tylko istotne fragmenty pliku różnicowego / poprawki na podstawie wyrażenia regularnego

20

git log -G<regex> -pto wspaniałe narzędzie do przeszukiwania historii bazy kodów w poszukiwaniu zmian pasujących do określonego wzorca. Jednak zlokalizowanie odpowiedniego przystojniaka na wyjściu diff / patch w morzu głównie nieistotnych przystani może być przytłaczające.

Oczywiście możliwe jest przeszukanie wyjściowego git logciągu / wyrażenia regularnego, ale to niewiele robi, aby zredukować wizualny szum i rozproszenie wielu niepowiązanych zmian.

Czytając dalej git log, widzę, że jest to --pickaxe-all, co jest dokładnym przeciwieństwem tego, czego chcę: poszerza wyjście (do całego zestawu zmian), podczas gdy chcę je ograniczyć (do określonego przystojniaka).

Zasadniczo szukam sposobu na „inteligentne” parsowanie pliku różnicowego / łaty do poszczególnych przystojniaków, a następnie przeprowadzenie wyszukiwania dla każdego przystojniaka (celowanie tylko w zmienione linie), odrzucenie kawałków, które nie pasują, i wysłanie tych to robi.

Czy istnieje takie narzędzie, jakie opisuję? Czy istnieje lepsze podejście do uzyskania pasujących / dotkniętych porcji?

Niektóre wstępne badania, które przeprowadziłem ...

  • Gdyby było to możliwe w grepprzypadku wyjścia diff / patch i uczynienie wartości opcji kontekstowych dynamicznymi - powiedzmy, przez wyrażenia regularne zamiast zliczania linii - może to wystarczyć. Ale grepnie jest zbudowany w ten sposób (niekoniecznie wymagam tej funkcji).

  • Znalazłem pakiet patchutils , który początkowo wydawał się odpowiedni dla moich potrzeb. Ale po przeczytaniu jego manstron narzędzia wydają się nie obsługiwać pasujących fragmentów na podstawie wyrażeń regularnych. (Mogą zaakceptować listę przystojniaków, choć ...)

  • W końcu natknąłem się na splitpatch.rb , który wydaje się dobrze radzić sobie z parsowaniem łatki, ale trzeba by go znacznie rozszerzyć, aby obsługiwać łatki do czytania stdin, dopasowując pożądane fragmenty, a następnie generując fragmenty.

wrksprfct
źródło
1
Nie dokładnie to, o co prosiłeś, ale spróbuj git log -Gfoo | mniej + / foo
James Youngman

Odpowiedzi:

7

tutaj /programming//a/35434714/5305907 opisano sposób robienia tego, czego szukasz. efektywnie:

git diff -U1 | grepdiff 'console' --output-matching=hunk

Pokazuje tylko fragmenty pasujące do podanego ciągu „konsola”.

nagu
źródło
dzięki. grepdiffjest w zasadzie tym, czego chcę; musiałem przegapić opcję dopasowywania przystojniaków! jednakże ... informacje git commit są usuwane grepdiff, więc po zlokalizowaniu odpowiedniego przystawki musisz rozpoznać zatwierdzenie sha z obiektu / obiektu blob sha w nagłówku diff - dość kosztowna operacja. (patrz stackoverflow.com/a/223890/2284440 ) byłoby to coś w rodzajugit find-object SHA --reverse | head -1 | cut -c 1-7 | { read sha ; git log -1 $sha; }
wrksprfct
zauważ także, że istnieje wersja golang,grepdiff która jest bardziej oklepana pod względem przyjętych argumentów. zwróć uwagę, że gdy dopasowany przystojniak jest ostatnim przystojniakiem w pliku różnicowym, niepoprawnie zawiera nagłówek git commit następnego zatwierdzenia - coś, co całkowicie mnie pomieszało, dopóki nie zdałem sobie sprawy, co się dzieje!
wrksprfct
0

Niezupełnie to, o co prosisz, ale jednym ze sposobów na przechodzenie między kawałkami jest tryb dodawania interaktywnego. Wymaga to sprawdzenia zatwierdzenia po łatce, którą jesteś zainteresowany

git checkout COMMIT_ID

następnie cofnij się o jeszcze jeden krok w VCS, ale nie w katalogu roboczym

git reset --soft HEAD^

(W tym momencie różnica między indeksem a katalogiem roboczym będzie odpowiadać łatce, którą jesteś zainteresowany.)

Możesz teraz wykonać git add -p. To uruchomi interaktywną sesję z /opcją, która pozwala zlokalizować przystojniaki, w których niektóre wiersze pasują do wyrażenia regularnego. Jest to szczególnie przydatne, jeśli chcesz dalej przetwarzać te łatki (np. Przygotować częściowy wybór wiśni).

Niestety, przynajmniej w tej chwili /polecenie add -pdziała tylko w obrębie jednego pliku, więc może być konieczne pominięcie kilku niepotrzebnych plików.

po lewej stronie
źródło
0

Opierając się na powyższej odpowiedzi @nagu i innych połączonych odpowiedziach, udało mi git log -Gsię wyświetlić tylko odpowiednie fragmenty.

  1. Najpierw utwórz skrypt gdzieś w $ PATH z tą zawartością:

    #!/bin/bash
    
    # pickaxe-diff : external diff driver for Git.
    #                To be used with the pickaxe options (git [log|show|diff[.*] [-S|-G])
    #                to only show hunks containing the searched string/regex.
    
    path=$1
    old_file=$2
    old_hex=$3
    old_mode=$4
    new_file=$5
    new_hex=$6
    new_mode=$7
    
    filtered_diff=$(diff -u -p $old_file $new_file | \
                    grepdiff "$GREPDIFF_REGEX" --output-matching=hunk | \
                    grep -v -e '+++ ' -e '--- ')
    
    a_path="a/$path"
    b_path="b/$path"
    
    echo "diff --git $a_path $b_path"
    echo "index $old_hex..$new_hex $old_mode"
    echo "--- $a_path"
    echo "+++ $b_path"
    echo "$filtered_diff"
  2. Zadzwoń git log -Gi powiedz Gitowi, aby używał pickaxe-diffskryptu jako zewnętrznego sterownika różnicowego:

    export GREPDIFF_REGEX=<string>; 
    GIT_EXTERNAL_DIFF=pickaxe-diff git log -p --ext-diff -G $GREPDIFF_REGEX

    Spowoduje to użycie skryptu kilof-diff tylko do wygenerowania różnic, więc reszta danych git logwyjściowych (skrót mieszania, komunikat itp.) Pozostanie nietknięta.

Ostrzeżenie
Sposób, w jaki działa kilof Gita, polega na tym, że ogranicza on dane wyjściowe do plików, których porcje zmieniają podany ciąg / wyrażenie regularne. Oznacza to, że jeśli inny przystojniak w tych plikach również zawiera szukany ciąg / wyrażenie regularne, ale go nie zmienia, nadal będzie wyświetlany z powyższym skryptem. Jest to ograniczenie grepdiff. W projekcie patchutils jest otwarte żądanie ściągnięcia, aby dodać --only-matchingflagę do grepdiff, co zapewniłoby niezbędną funkcjonalność, aby poprawnie odfiltrować te porcje.


W tym artykule napisałem swoje rozwiązanie .

philb
źródło