Git winić - wcześniejsze zobowiązania?


390

Czy można zobaczyć, kto edytował określoną linię przed zgłoszonym zatwierdzeniem git blame, jak historia zatwierdzeń dla danej linii?

Na przykład uruchamiam następujące (w znakomitym uncrustifyprojekcie):

$ git blame -L10,+1 src/options.cpp
^fe25b6d (Ben Gardner 2009-10-17 13:13:55 -0500 10) #include "prototypes.h"

Jak mogę dowiedzieć się, kto edytował ten wiersz przed zatwierdzeniem fe25b6d? A kto go edytował przed tym zatwierdzeniem?


7
jeśli powodem szukania poprzednich zatwierdzeń są zmiany białych znaków, użyj -wopcji. Istnieje również -Mprzeniesiony / skopiowany kod
brita_

Aby wyszukać wszystkie zatwierdzenia, które zawierają dane słowo, zobacz mój skrypt poniżej
VonC

Oto przydatny skrypt do dodania tej funkcji na github greasyfork.org/en/scripts/…
Aaron Hoffman

3
Nie jestem pewien, jak wyglądał github, gdy napisał @AaronHoffman, ale o wiele łatwiej jest obwiniać - i obwiniać za poprzednie wersje - teraz w github .
ruffin

Odpowiedzi:


389
git blame -L 10,+1 fe25b6d^ -- src/options.cpp

Możesz określić wersję dla git blame, która będzie wyglądać wstecz (zamiast domyślnej HEAD); fe25b6d^jest rodzicem fe25b6d.


106
Czy możesz uzyskać pełną historię bez konieczności ponownego wprowadzania polecenia kilka razy z różnymi skrótami?
Anders Zommarin

13
Nie wierzę, że Git ma wbudowany sposób na uzyskanie każdej winy, która dotknęła numeru linii (co ma sens, ponieważ dana linia może nie mieć spójnego numeru linii w całej historii pliku z powodu wstawiania i usuwania linii).
Amber

17
@Amber: Jestem pewien, że masz rację, że ta funkcja nie istnieje, ale wygląda na to, że można ją zaimplementować naiwnie, po prostu robiąc to, co zrobiłby człowiek: obwiniaj ją raz, chwyć zgłoszone informacje, obwiniaj to , i tak dalej.
Cascabel

15
git gui ułatwia sprawdzenie historii linii, ponieważ wersje można klikać.
Zitrax,

5
@shadyabhi --jest powszechnie używany jako separator w argumentach wiersza poleceń - w przypadku Git zwykle służy do oddzielania rzeczy takich jak skróty zatwierdzania od listy nazw plików.
Amber

191

Możesz użyć git log -L, aby zobaczyć ewolucję zakresu linii.

Na przykład :

git log -L 15,23:filename.txt

oznacza „śledź ewolucję linii od 15 do 23 w pliku o nazwie nazwa_pliku.txt”.


12
To solidna odpowiedź i odpowiada na powyższe pytanie Andersa Zommarina, w jaki sposób zobaczyć zmiany poszczególnych linii w czasie.
bigtex777,

4
FYI: git log -L <start>, <end>: <plik> wymaga Git 1.8.4+ patrz: git-scm.com/docs/git-log#git-log--Lltstartgtltendgtltfilegt dla opcji składni
Neon

30

Odpowiedź Ambera jest prawidłowa, ale ja niejasne; Składnia jest następująca:

git blame {commit_id} -- {path/to/file}

Uwaga: --służy do oddzielenia drzewa sha1 od względnych ścieżek plików. 1

Na przykład:

git blame master -- index.html

Pełne uznanie dla Amber za znajomość wszystkich rzeczy! :)


1
Zgadzam się z twoim sentymentem. System komentarzy jest jednak zbyt ograniczony, aby wyraźnie prezentować wszystkie informacje. Dodałem treść tej odpowiedzi w komentarzu; nalegam jednak, aby pozostawić tę odpowiedź dla łatwego dostępu.
ThorSummoner

1
Powinien to być oddzielny post lub edycja. Podoba mi się to jako osobna odpowiedź.
Flimm

27

Może chcesz sprawdzić:

git gui blame <filename>

Daje ładny graficzny obraz zmian, takich jak „git blame”, ale z klikalnymi linkami w wierszu, aby przejść do wcześniejszych zatwierdzeń. Najedź kursorem na linki, aby wyświetlić wyskakujące okienko ze szczegółami zatwierdzenia. Nie moje kredyty ... znalazłem to tutaj:

http://zsoltfabok.com/blog/2012/02/git-blame-line-history/

git guito graficzny interfejs Tcl / Tc do git. Bez żadnych innych parametrów uruchamia dość prostą, ale przydatną aplikację graficzną do zatwierdzania plików, kawałków, a nawet pojedynczych linii i innych podobnych poleceń, takich jak poprawianie, przywracanie, wypychanie ... To część pakietu git stock. W systemie Windows jest on zawarty w instalatorze. W systemie Debian - nie wiem o innych systemach * nix - musi być zainstalowany osobno:

apt-get install git-gui

Z dokumentów:

https://git-scm.com/docs/git-gui

OPIS

Graficzny interfejs użytkownika oparty na Tcl / Tk dla Git. git gui koncentruje się na umożliwieniu użytkownikom dokonywania zmian w repozytorium poprzez wprowadzanie nowych zatwierdzeń, modyfikowanie istniejących, tworzenie oddziałów, wykonywanie lokalnych scaleń oraz pobieranie / wypychanie do zdalnych repozytoriów.

W przeciwieństwie do gitk, git gui koncentruje się na generowaniu zatwierdzeń i adnotacjach pojedynczych plików i nie pokazuje historii projektu. Dostarcza jednak akcji menu, aby rozpocząć sesję gitk z poziomu git gui.

git gui działa na wszystkich popularnych systemach UNIX, Mac OS X i Windows (zarówno pod Cygwin, jak i MSYS). W możliwym zakresie przestrzegane są wytyczne dotyczące interfejsu użytkownika specyficzne dla systemu operacyjnego, dzięki czemu git gui jest dość natywnym interfejsem dla użytkowników.

POLECENIA

winić

Uruchom przeglądarkę obwiniania określonego pliku w danej wersji (lub katalogu roboczego, jeśli nie został określony).

przeglądarka

Uruchom przeglądarkę drzewa pokazującą wszystkie pliki w określonym zatwierdzeniu. Pliki wybrane w przeglądarce są otwierane w przeglądarce winy.

citool

Uruchom git gui i ustaw dokładnie jedno zatwierdzenie przed wyjściem i powrotem do powłoki. Interfejs ogranicza się tylko do zatwierdzania działań, co nieco skraca czas uruchamiania aplikacji i upraszcza pasek menu.

wersja

Wyświetl aktualnie działającą wersję git gui.


To nie działa dla mnie. Mogę kliknąć zmianę w podanej linii, ale to po prostu zmienia widok dla tego zatwierdzenia, a bieżąca linia pokazuje teraz jako this: ale jak widzę poprzednią wersję linii i kiedy została dodana?
BeeOnRope

Jest to jedyny znany mi przypadek użycia, gdzie git gui jest najlepszym rozwiązaniem
kambuzujący

17

Opierając się na poprzedniej odpowiedzi, ten bash jednoliniowy powinien dać ci to, czego szukasz. Wyświetla historię obwiniania git dla konkretnego wiersza określonego pliku, z ostatnich 5 wersji:

LINE=10 FILE=src/options.cpp REVS=5; for commit in $(git rev-list -n $REVS HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done

W wyniku działania tego polecenia możesz zobaczyć treść zmiany linii, lub wyświetlony numer linii może nawet ulec zmianie, dla konkretnego zatwierdzenia.

Często oznacza to, że wiersz został dodany po raz pierwszy, po tym konkretnym zatwierdzeniu. Może to również oznaczać, że linia została przeniesiona z innej części pliku.


5
Zauważ, że są to ostatnie wersje $ REVS, w których zmieniono $ FILE, a nie ostatnie wersje $ REVS, w których zmieniono $ LINE.
Max Nanasy 13.03.2013

Do jakiej odpowiedzi się odnosisz?
Flimm

Już nie pamiętam. Być może mógłbym lepiej przygotować moją odpowiedź na przyszłość.
Will Sheppard


11

Bardzo unikalnym rozwiązaniem tego problemu jest użycie git log:

git log -p -M --follow --stat - ścieżka / do / twojego / pliku

Jak wyjaśnił Andre tutaj


1
Utworzyłem alias, aby tego użyć: git config --global alias.changes 'log -p -M --follow --stat --'a potem mogę po prostu wpisaćgit changes path/to/your/file
Tizio Fittizio,

To zdecydowanie najlepsza odpowiedź i dokładnie tego szukałem. Prosty i elegancki.
maesk

10

Jeśli używasz JetBrains Idea IDE (i pochodnych), możesz wybrać kilka linii, kliknij prawym przyciskiem myszy menu kontekstowe, a następnie Git -> Pokaż historię do wyboru. Zobaczysz listę zatwierdzeń, które miały wpływ na wybrane linie:

wprowadź opis zdjęcia tutaj


Działa to lepiej niż inne odpowiedzi dla mnie (przy użyciu IntelliJ). Zajęło trochę czasu, aby załadować wszystkie wersje, ale warto poczekać.
Steve Chambers

1

Opierając się na odpowiedzi Willa Sheparda, jego wyniki będą zawierać duplikaty wierszy dla zatwierdzeń, w których nie było zmian, więc możesz je filtrować w następujący sposób (używając tej odpowiedzi )

LINE=1 FILE=a; for commit in $(git rev-list HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

Zauważ, że usunąłem argument REVS i to wraca do głównego zatwierdzenia. Wynika to z powyższej obserwacji Maxa Nanasy'ego.


1

Opierając się na odpowiedzi Davida, chcę śledzić plik o zmienionej nazwie:

LINE=8 FILE=Info.plist; for commit in $(git log --format='%h%%' --name-only --follow -- $FILE | xargs echo | perl -pe 's/\%\s/,/g'); do hash=$(echo $commit | cut -f1 -d ','); fileMayRenamed=$(echo $commit | cut -f2 -d ','); git blame -n -L$LINE,+1 $hash -- $fileMayRenamed; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

ref: ładnie wyświetla historię zmian nazw plików w git log


1

Od wersji Git 2.23 możesz korzystać git blame --ignore-rev

Dla przykładu podanego w pytaniu byłoby to:

git blame -L10,+1 src/options.cpp --ignore-rev fe25b6d

(jest to jednak podchwytliwe pytanie, ponieważ fe25b6d to pierwsza wersja pliku!)


0

Używam tego małego skryptu bash, aby zobaczyć historię winy.

Pierwszy parametr: plik do obejrzenia

Późniejsze parametry: Przekazano na winę git

#!/bin/bash
f=$1
shift
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    echo "--- $hash"
    git blame $@ $hash -- "$f" | sed 's/^/  /'
  done
}

Możesz podać parametry winy, takie jak -L 70, + 10, ale lepiej jest użyć wyszukiwania wyrażenia regularnego git winy, ponieważ numery linii zwykle „zmieniają się” w czasie.


0

Budowa na stangls „s odpowiedź , mogę umieścić ten skrypt na mojej drodze (nawet w systemie Windows), jak git-BH:

To pozwala mi szukać wszystkich zatwierdzeń, w których było zaangażowane słowo:

git bh path/to/myfile myWord

Scenariusz:

#!/bin/bash
f=$1
shift
csha=""
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    res=$(git blame -L"/$1/",+1 $hash -- "$f" 2>/dev/null | sed 's/^/  /')
    sha=${res%% (*}
    if [[ "${res}" != "" && "${csha}" != "${sha}" ]]; then
      echo "--- ${hash}"
      echo "${res}"
      csha="${sha}"
    fi
  done
}
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.