Jak znaleźć najnowsze zatwierdzenie git, które zmodyfikowało plik?

180

Chcę znaleźć najnowsze zatwierdzenie, które zmodyfikowało plik źródłowy.

Mogę użyć, git blameaby zobaczyć wszystkie daty zatwierdzeń w każdym wierszu, ale trudno jest dokładnie zobaczyć, który commit jako ostatni dotknął pliku.

Jak mogę znaleźć ostatnie zatwierdzenie, które dotknęło danego pliku w moim repozytorium git?

Cory Klein
źródło

Odpowiedzi:

230

git log obsługuje przeglądanie historii określonych plików (i katalogów), więc możesz to nazwać tak:

git log my/file.c

Jeśli naprawdę chcesz wyświetlić tylko jedno ostatnie zatwierdzenie, na przykład użyć go w skrypcie, użyj -n 1opcji:

git log -n 1 --pretty=format:%H -- my/file.c

--pretty=format:%hkaże git logpokazać tylko skrót zatwierdzenia. --Separater zatrzymuje nazwę pliku z coraz interpretowane jako popełnić imię, na wszelki wypadek jest niejednoznaczna.

Jo Liss
źródło
12
Jeśli chcesz wiedzieć, kiedy ostatnio plik był modyfikowany bez względu na gałąź, możesz rozważyć wszystkie gałęzie, dodając --allopcję.
KC
44

Jeśli chcesz tylko znaleźć najnowsze zatwierdzenie, to nie chcesz git-log, chcesz git-rev-list, które zawiera listę obiektów zatwierdzeń zmieniających ten plik, w tej ścieżce zatwierdzenia, zaczynając od najnowszego (chronologicznie). Mówiąc najprościej:

git rev-list -1 <commit> <filename>

W git-rev-listtwoim przypadku wystarczy podać:

  • Liczba zatwierdzeń do uwzględnienia lub -1 tylko dla najnowszych,
  • Gałąź (lub identyfikator zatwierdzenia), od której ma się rozpocząć oglądanie wstecz, HEAD, jeśli już na niej jesteś, lub --all jeśli chcesz wszystkie znane zobowiązuje, a
  • Względna ścieżka do twojego pliku.

To po prostu zwraca ostatni identyfikator zatwierdzenia w bieżącej gałęzi, aby zmienić ten plik, np: 215095e2e338525be0baeeebdf66bfbb304e7270

Aby uzyskać bardziej złożony przykład, możesz użyć nazw tagów, a nawet zdalnych odwołań, i dołączyć względne nazwy ścieżek z symbolami wieloznacznymi, na przykład:

git rev-list origin/user/bob/testbranch -1 src/bfiles/*.txt

... Który powiedziałby ci, jaka była ostatnia zmiana w dopasowaniu symboli wieloznacznych w historii tej gałęzi. Opcje listy obrotów są ekstremalne, jest to jedno z najważniejszych poleceń hydraulicznych, więc możesz uwzględnić lub wykluczyć dowolne kryteria, jakie możesz sobie wyobrazić.

Oczywiście zajrzyj na stronę podręcznika git-rev-list (1) .

Michael Erickson
źródło
Naprawdę nie wyjaśniłeś, dlaczego używanie git-logjest gorsze.
Piotr Dobrogost
7
Nie powiedziałbym gorszy, tylko że domyślnie dostarcza zbędnych informacji. git-rev-list po prostu zwraca identyfikator zatwierdzenia, który jest tym, czego potrzebujesz, jeśli chcesz przesłać odpowiedź do skryptu lub innego procesu automatyzacji. git-log zwraca informacje o wybranych zatwierdzeniach, najpierw używając git-rev-list do zebrania identyfikatorów zatwierdzeń, a następnie zbierając informacje o każdym zatwierdzeniu. Jeśli zamierzasz po prostu odfiltrować informacje o zatwierdzeniu i użyć identyfikatorów, możesz po prostu użyć git-rev-list w pierwszej kolejności. Ponieważ dziennik jest oparty na liście obrotów, przyjmuje większość tych samych parametrów filtru.
Michael Erickson
3
git-logto porcelana, git-rev-listhydraulika.
blitzen9872
27

Jeśli chcesz po prostu uzyskać hash ostatniego zatwierdzenia, aby zmodyfikować określony zestaw plików (i chcesz tego uniknąć awk), możesz użyć:

git log -n 1 --pretty=format:%h -- <path>

Może to być przydatne do uzyskania skrótu zatwierdzenia do późniejszego użycia z git describe.

Na przykład (jeśli jest to przydatne dla każdego)…

Tworzę identyfikator bieżącej wersji, biorąc pod uwagę ostatnie zatwierdzenie zmiany dowolnego pliku źródłowego (zakładając, że oznaczasz wersje tagami takimi jak mycode-1.2.1):

COMMIT=$(git log -n 1 --pretty=format:%h -- *.c *.h)
if VN=$(git describe --always --abbrev=5 --match "mycode-*" $COMMIT 2>/dev/null) &&
case "$VN" in
mycode-*)
    git update-index -q --refresh
    test -z "$(git diff-index --name-only HEAD *.c *.h)" ||
    VN="$VN-mod" ;;
*) VN="mycode-unknown-g$VN" ;;
esac
then
    continue
else
VN="mycode-unknown"
fi

Daje to identyfikatory takie jak:

  • mycode-1.2.1 - kiedy aktualny stan plików źródłowych odpowiada wersji oznaczonej
  • mycode-1.2.1-g3k7s2 - kiedy aktualny stan plików źródłowych odpowiada zatwierdzeniu po oznaczonej wersji
  • mycode-1.2.1-g3k7s2-mod - gdy aktualny stan plików źródłowych został zmodyfikowany od ostatniego zatwierdzenia następującego po oznaczonej wersji
  • mycode-unknown - gdy nie został jeszcze utworzony tag wersji
TheBamf
źródło
5
$VNwygląda jak jakiś koszmar nieumarłych SVN
ThorSummoner
10

Nie jestem pewien, czy tego chcesz, ale jeśli zrobisz, git log <thefile>aby uzyskać zatwierdzenia, które zmieniły ten plik. Możesz wybrać najwyższy. Powinien to być ten, którego szukasz.

Noufal Ibrahim
źródło
4
jeśli używasz git log -n1 -- <thefile>(lub przelać wyjście head -1, jeśli chcesz marnować zasobów) nie trzeba ręcznie wybrać linię górną (patrz Jo Liss za odpowiedź )
Tobias Kienzler
4
Słuszna uwaga. Myślę, że możesz również pominąć -ni użyć -1bezpośrednio.
Noufal Ibrahim
3

Aby uzyskać tylko ref w jednej linii, spróbuj:

git log -n1 --oneline <path> | awk '{print $1;}'
szybkie mnożenie
źródło
2

Kiedy już masz identyfikator SHA zatwierdzenia, którego chcesz używać git log FILENAME, powinieneś być w stanie git show SHA_ID_HEREzobaczyć, co zrobiłeś dla tego konkretnego zatwierdzenia. Nie musisz nawet wpisywać całego identyfikatora; pierwszych 6 znaków powinno wystarczyć.

Joe
źródło
4
to trochę więcej niż żądano PO, ale do Twojej wiadomości możesz połączyć to w jedną linijkę:git show $(git log -1 --pretty="%H" -- FILENAME)
Tobias Kienzler