Jak mogę uzyskać różnicę między wszystkimi zatwierdzeniami, które miały miejsce między dwiema datami w Git?

117

A może tylko wszystkie zatwierdzenia, które miały miejsce między dwiema datami? W SVN możesz zrobić coś takiego

svn diff -r{date}:{date}

zrobić to! Nie mogę znaleźć odpowiednika tego w Gicie.

W szczególności zajmuję się napisaniem skryptu do codziennego wysyłania e-maili z całym kodem popełnionym tego dnia i przez kogo.

Chris
źródło

Odpowiedzi:

160

Możesz użyć git whatchanged --since="1 day ago" -p

Wymaga również --untilkłótni.

Dokumenty

seth
źródło
dzięki! To było słuszne, czego chciałem, nawet przyjmuje parametr --committer, chociaż nie ma go w dokumentacji! również „git whatchanged” nie pojawiło się w „git help”! Nie mam pojęcia, dlaczego ... jeszcze raz dziękuję.
Chris,
5
Powinieneś ustawić tę odpowiedź jako wybraną, aby seth otrzymał trochę karmy.
Scott,
18
@brbob Wiem, że odpowiedź na to pytanie udzielono dawno temu, ale tylko dla kogoś, kto natknie się na to (tak jak ja) Pomoc Git mówi: The command is kept primarily for historical reasons; fingers of many people who learned Git long before git log was invented by reading Linux kernel mailing list are trained to type it. Tak więc docs zachęca do używania git logzamiast git whatchanged; to ostatnie polecenie używa również opcji --no-merge git log, więc wyświetlają te same wyniki.
Ramzes
2
git whatchanged jest rodzajem aliasu polecenia git log zgodnie z dokumentacją git log
Vincent
2
git whatchangedjest przestarzałe od najnowszej wersji 2.21.0. Wszystko git whatchangedto można osiągnąć git logi jest to zachowane tylko ze względów historycznych. Zobacz szczegóły git-scm.com/docs/git-whatchanged/2.21.0
Devy
60

Poprzednie sugestie mają pewne wady. Zasadniczo szukałem czegoś równoważnego cvs diff -D"1 day ago" -D"2010-02-29 11:11". Zbierając coraz więcej informacji, znalazłem rozwiązanie.

Rzeczy, których próbowałem:

  • git whatchanged --since="1 day ago" -pod tutaj

    Ale to daje różnicę dla każdego zatwierdzenia, nawet jeśli w jednym pliku jest wiele zatwierdzeń. Wiem, że „randka” to trochę luźna koncepcja w gicie , pomyślałem, że musi być jakiś sposób, aby to zrobić.

  • git diff 'master@{1 day ago}..masterostrzega warning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100.i nie pokazuje wszystkich różnic.

  • git format-patch --since=yesterday --stdout nic za mnie nie daje.

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) działa jakoś, ale wydaje się skomplikowany i nie ogranicza się do aktualnej branży.

Wreszcie:

Co zabawne, git-cvsserver nie obsługuje "cvs diff -D" (bez tego jest to gdzieś udokumentowane).

Weidenrinde
źródło
4
+1 za git rev-list, co znacznie przyczyniło się do rozwiązania bardzo podobnego problemu, który widziałem.
me_and
To nie powinna być akceptowana odpowiedź, setha jest bardziej zwięzła i poprawna.
ctford
6
@ctford, moim zdaniem, nie jest to poprawne. Może zgłaszać wiele różnic dla jednego pliku, a nie jednego pliku różnicowego w postaci svn / cvs diff.
Weidenrinde
1
@Weidenrinde +1, to jest znacznie sprytniejsze
rostamn739
1
Te git diff 'master@{1 day ago}..masterśrodki składniowe „sprawdzić się reflog i dowiedzieć się, gdzie oddział masterwykorzystywane do punktu w lokalnym repozytorium 1 day ago ”. W szczególności nie będzie używać rzeczywistej historii zatwierdzania bieżącej gałęzi master. Bardzo rzadko jest to rzecz, której naprawdę chcesz.
Mikko Rantalainen
22

„Date” to trochę luźna koncepcja w gicie. Zatwierdzenie będzie miało datę autora, która może znajdować się w przeszłości, zanim ktoś faktycznie pobierze / zatwierdzi zatwierdzenie do swojego repozytorium, również zatwierdzenie może zostać zmienione i zaktualizowane, aby znajdowało się na szczycie pozornie nowszego zatwierdzenia.

Zatwierdzenie ma również datę zatwierdzenia, która jest aktualizowana, jeśli zatwierdzenie zostanie zmienione lub w jakikolwiek sposób zmienione. Te zatwierdzenia są bardziej prawdopodobne w jakiejś kolejności chronologicznej, ale nadal jesteś na łasce osoby zatwierdzającej, która ma właściwy czas ustawiony na swoim komputerze, a mimo to niezmodyfikowane zatwierdzenie może siedzieć w gałęzi funkcji w zdalnym repozytorium przez czas nieokreślony scalane z główną gałęzią centralnego repozytorium.

To, co jest prawdopodobnie najbardziej przydatne do twoich celów, to data reflogu w określonym repozytorium. Jeśli masz włączone reflogs dla poszczególnych gałęzi (zobacz git config core.logAllRefUpdates), możesz użyć ref@{date}składni, aby odnieść się do miejsca, w którym gałąź była w określonym czasie.

Na przykład

git log -p master@{2009-07-01}..master@{now}

Możesz także użyć „rozmytych” opisów, takich jak:

git log -p "master@{1 month ago}..master@{yesterday}"

Te polecenia pokażą wszystkie zatwierdzenia, które „pojawiły się” w danej gałęzi repozytorium, niezależnie od tego, jak są „stare” według ich autora i dat wprowadzenia.

Zwróć uwagę, że reflog dla poszczególnych gałęzi jest specyficzny dla repozytorium, więc jeśli uruchamiasz polecenie dziennika na klonie i nie ściągasz przez (powiedzmy) miesiąc, a następnie pobierz wszystkie zmiany z ostatniego miesiąca naraz wtedy wszystkie zmiany z ostatniego miesiąca pojawią się w @{1 hour ago}..@{now}zakresie. Jeśli jesteś w stanie uruchomić polecenie log w „centralnym” repozytorium, do którego ludzie naciskają, może to zrobić, co chcesz.

CB Bailey
źródło
Bardzo dobry opis i dobra odpowiedź na zadane pytanie ... ale myślę, że nie pomogłoby to zbytnio w zrobieniu tego, co zamierzał Brbob.
Jakub Narębski
To zależy, może pomóc, jeśli rzeczywiście chce przeanalizować to, co zostało przesłane do określonej gałęzi w pewnym centralnym repozytorium, a polecenie dziennika zostało uruchomione w tym repozytorium. Myślę, że zmiana jest w porządku ...
CB Bailey,
„data zatwierdzenia, która jest aktualizowana, jeśli zatwierdzenie zostanie zmienione lub w jakikolwiek sposób zmienione”, w rzeczywistości data nigdy nie jest zmieniana; całe zatwierdzenie zostaje zastąpione innym zatwierdzeniem (chociaż drzewo mogłoby być takie samo).
hasen
2
@hasen j: Technicznie masz rację. Zatwierdzenia są niezmienne. Kiedy rebase lub poprawiasz zatwierdzenie i tworzysz nowy, istniejący komunikat o zatwierdzeniu, dane autora i data autora są często kopiowane ze starego zatwierdzenia, więc to tak , jakbyś aktualizował zatwierdzenie o nowy identyfikator i datę zatwierdzenia.
CB Bailey
Zauważ, że @{time spec}składnia zawsze odnosi się do twojego lokalnego reflogu . Nie odnosi się do aktualnej historii zatwierdzeń (DAG). Jeśli nie rozumiesz różnicy, nie używaj tej składni!
Mikko Rantalainen
14
git diff --stat @{2013-11-01}..@{2013-11-30}

lub

git diff --stat @{2.weeks.ago}..@{last.week}
AA.
źródło
Czy to zależy od reflogu? Ponieważ jeśli tak, to nie możesz tego użyć, jeśli repozytorium, w którym uruchamiasz to polecenie, jest nowsze (tj. Świeżo sklonowane) niż historia zmian, które zawiera.
2
Tak, to całkowicie zależy od reflogu. I tak, to działa tylko w lokalnej historii kopiowania, ale jest trochę wygodnym poleceniem.
AA.
1
Tak, zdecydowanie zgadzam się, że jest to wygodne, o ile masz wpisy reflog na tyle stare, aby to obsługiwać.
Dziękuję AA. Korzystając z Twojej odpowiedzi, byłem w stanie wykonać: git annotate --stat .. @ {2017-08-8} nazwa_pliku | less; git annotate --stat .. @ {5.days.ago} nazwa_pliku; więc mogę zobaczyć zmiany w kontekście.
Chris,
Zauważ, że @{time spec}składnia zawsze odnosi się do twojego lokalnego reflogu . Nie odnosi się do aktualnej historii zatwierdzeń (DAG). Jeśli nie rozumiesz różnicy, nie używaj tej składni!
Mikko Rantalainen
4

Być może

$ git format-patch --committer=<who> --since=yesterday --stdout

jest tym, czego chcesz (z opcją „--stdout” lub bez niej)?

Jakub Narębski
źródło
1
Szybkie pytanie, czy - od czasu użycia daty zatwierdzenia?
CB Bailey,
3

Uważam, że ogólnym rozwiązaniem jest użycie:

git rev-list -n1 --first-parent --until=<a date string> <a ref>

Bez --first-parent, możesz otrzymać zatwierdzenie z gałęzi, która została później scalona, a refale nie została scalona w dniu a date string.

Oto alternatywa użycia --childreni grepzamiast -n1:

mlm_git_ref_as_of() {
    # # Examples #
    #
    # Show all commits between two dates:
    #
    #     git log $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    #
    # Show diffs of all commits between two dates:
    #
    #     git diff $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    local as_of="$1"
    local ref="${2:-HEAD}"
    # Get the most recent commit (--children, grep -v ' ') that was on
    # the given branch ($ref, --first-parent) as of a given date
    # ($as_of)
    git rev-list --children --first-parent --until="$as_of" "$ref" | grep -v ' '
}

Nie byłem zaznajomiony z tym git whatchangedprzed przeczytaniem tego pytania i odpowiedzi, ale daje on bardzo różne wyniki, więc nie jestem pewien, co robi.

Matt McClure
źródło
3

Innym prostym sposobem na uzyskanie różnicy wszystkich zmian od określonej daty jest po prostu znalezienie pierwszego zatwierdzenia, Xktóre miało miejsce tego dnia lub później, a następnie użycie

git diff X

Ma to tę zaletę, że nie zależy od wpisów reflog w nowym klonie, w przeciwieństwie do

git diff <reference>@{n}..
git log <reference>@{n}..

rozwiązania w

Społeczność
źródło
3

Aby obserwować zmiany plików Git od początku do chwili w Twoim oddziale, użyj następującej formuły:

  1. sprawdź swój oddział.
  2. pobrać i zaktualizować zmiany ze zdalnego repozytorium
  3. oglądaj pliki różnicowe od daty do zakresu dat

Formuła :

git checkout <branch>
git pull
git diff --stat @{fromDate}..@{toDate}

Zwróć uwagę, że daty są w formacie RRRR-MM-DD :

git diff --stat @{2019-08-20}..@{2019-08-21}

Jeśli chcesz obserwować zmiany w określonym pliku w określonym przedziale czasu (obserwuj różnice w kodzie), po prostu przejdź do bieżącego pliku:

Przykład :

git diff @{2019-01-01}..@{2019-01-02} ~/dev/myApp/package.json
avivamg
źródło
2

To bardziej zabawna odpowiedź, ponieważ prawdopodobnie istnieje lepszy sposób. Spowoduje to wyświetlenie wszystkich wartości skrótu zatwierdzania na dziś.

git log --pretty="format:%H %ai" | grep `date +"%Y-%m-%d"` | awk {'print $1'}`

; ·)

gahooa
źródło
2

Możesz także użyć git-format-patch do przygotowania łatek (różnic) i wysłania ich pocztą elektroniczną.

Użyj opcji [od] lub [zakres wersji], aby określić zakres zatwierdzeń.

Nick Dandoulakis
źródło
0

Wrzucę sposób, w jaki to robię: git logdla daty podaje skróty zatwierdzeń dla bieżącej gałęzi. Następnie używam czegoś takiego, git diff 8fgdfg8..565k4l5co daje mi właściwą różnicę agregowaną według plików. Mam nadzieję, że to pomoże, chociaż nie testowałem zbyt wiele

rostamn739
źródło