Wie kann ich den Unterschied zwischen allen Commits ermitteln, die zwischen zwei Daten mit Git aufgetreten sind?

116

Oder nur alle Commits, die zwischen zwei Daten stattgefunden haben? In SVN können Sie so etwas tun

svn diff -r{date}:{date}

es zu tun! Ich kann anscheinend kein Git-Äquivalent dazu finden.

Insbesondere möchte ich ein Skript schreiben, um täglich E-Mails mit dem gesamten Code zu versenden, der an diesem Tag festgeschrieben wurde, und von wem.

Chris
quelle

Antworten:

159

Du könntest benutzen git whatchanged --since="1 day ago" -p

Es braucht auch ein --untilArgument.

Docs

Seth
quelle
Vielen Dank! Dies war genau das, was ich wollte, es wird sogar der Parameter --committer verwendet, obwohl dies nicht in der Dokumentation aufgeführt ist! Außerdem wurde 'git whatchanged' nicht in 'git help' angezeigt! Keine Ahnung warum ... nochmals vielen Dank.
Chris
5
Sie sollten dies zu Ihrer gewählten Antwort machen, damit Seth etwas Karma bekommt.
Scott
18
@brbob Ich weiß, dass dies vor langer Zeit beantwortet wurde, aber nur für jemanden, der darauf stößt (wie ich), sagt die Git-Hilfe: 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. Also, die Dokumentation empfiehlt die Verwendung git loganstelle von git whatchanged; Dieser letzte Befehl verwendet auch die Option --no-merge des Git-Protokolls, sodass dieselben Ergebnisse ausgegeben werden.
Ramses
2
git whatchanged ist eine Art Alias ​​des Befehls git log gemäß dem Protokoll
Vincent
2
git whatchangedist ab der aktuellsten Version 2.21.0 veraltet. Alles git whatchangedErreichte kann erreicht werden git logund ist nur aus historischen Gründen erhalten. Siehe Details git-scm.com/docs/git-whatchanged/2.21.0
Devy
60

Die vorherigen Vorschläge haben einige Nachteile. Grundsätzlich suchte ich etwas Äquivalentes zu cvs diff -D"1 day ago" -D"2010-02-29 11:11". Während ich immer mehr Informationen sammelte, fand ich eine Lösung.

Dinge, die ich versucht habe:

  • git whatchanged --since="1 day ago" -pvon hier

    Dies ergibt jedoch einen Unterschied für jedes Commit, selbst wenn eine Datei mehrere Commits enthält. Ich weiß, dass "Date" in Git ein etwas lockeres Konzept ist. Ich dachte, es muss einen Weg geben, dies zu tun.

  • git diff 'master@{1 day ago}..mastergibt eine Warnung warning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100.und zeigt nicht alle Unterschiede.

  • git format-patch --since=yesterday --stdout gibt nichts für mich.

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) funktioniert irgendwie, scheint aber kompliziert und beschränkt sich nicht auf den aktuellen Zweig.

Schließlich:

Lustigerweise unterstützt git-cvsserver "cvs diff -D" nicht (ohne dass es irgendwo dokumentiert ist).

Weidenrinde
quelle
4
+1 für git rev-list, was einen großen Beitrag zur Lösung des sehr ähnlichen Problems geleistet hat, das ich gesehen habe.
me_and
Dies sollte nicht die akzeptierte Antwort sein, Seths ist prägnanter und korrekter.
Ctford
6
@ctford, meiner Meinung nach ist es nicht korrekt. Es werden möglicherweise mehrere Unterschiede für eine Datei gemeldet, nicht ein Unterschied pro Datei als svn / cvs diff.
Weidenrinde
1
@Weidenrinde +1, das ist viel schlauer
rostamn739
1
Die git diff 'master@{1 day ago}..masterSyntax bedeutet „überprüfen die reflog und herauszufinden , wo Zweig masterzu Punkt verwendet in Ihrem lokalen Repository 1 day ago “. Insbesondere wird der tatsächliche Festschreibungsverlauf des aktuellen Zweigs nicht verwendet master. Dies ist sehr selten das, was Sie wirklich wollen.
Mikko Rantalainen
22

"date" ist ein bisschen ein loses Konzept in git. Ein Commit hat ein Autorendatum, das möglicherweise einige Zeit in der Vergangenheit liegt, bevor jemand das Commit tatsächlich in sein Repository zieht / festschreibt. Außerdem kann das Commit neu basiert und aktualisiert werden, um über einem anscheinend neueren Commit zu liegen.

Ein Commit hat auch ein Commit-Datum, das aktualisiert wird, wenn ein Commit in irgendeiner Weise neu basiert oder geändert wird. Es ist wahrscheinlicher, dass diese Commits in einer chronologischen Reihenfolge vorliegen, aber Sie sind immer noch dem Committer ausgeliefert, der die richtige Zeit auf seinem Computer eingestellt hat. Trotzdem kann ein unverändertes Commit auf unbestimmte Zeit in einem Feature-Zweig in einem Remote-Repository gespeichert werden wird in den Hauptzweig eines zentralen Repositorys zusammengeführt.

Was für Ihre Zwecke wahrscheinlich am nützlichsten ist, ist das Reflog-Datum für das betreffende Repository. Wenn Sie Reflogs pro Zweig aktiviert haben (siehe git config core.logAllRefUpdates), können Sie mithilfe der ref@{date}Syntax angeben , wo sich ein Zweig zu einem bestimmten Zeitpunkt befand.

Z.B

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

Sie können auch 'Fuzzy'-Beschreibungen verwenden wie:

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

Diese Befehle zeigen alle Commits an, die in dem angegebenen Zweig des Repositorys "erschienen" sind, unabhängig davon, wie "alt" sie tatsächlich sind, je nach Autor und Commit-Datum.

Beachten Sie, dass das Reflog pro Zweig für ein Repository spezifisch ist. Wenn Sie also den Protokollbefehl auf einem Klon ausführen und nicht (sagen wir) einen Monat lang abrufen, ziehen Sie alle Änderungen für den letzten Monat auf einmal ab. Dann werden alle Änderungen des letzten Monats in einem @{1 hour ago}..@{now}Bereich angezeigt. Wenn Sie den Befehl log für das 'zentrale' Repostory ausführen können, auf das die Benutzer zugreifen, kann er das tun, was Sie möchten.

CB Bailey
quelle
Sehr gute Berichterstattung und gute Antwort auf die gestellte Frage ... aber ich denke, es würde nicht viel helfen, das zu tun, was brbob beabsichtigt hat.
Jakub Narębski
Es hängt davon ab, ob es tatsächlich hilfreich sein kann, wenn er tatsächlich analysieren möchte, was in einem bestimmten Zweig in einem bestimmten zentralen Repository verschoben wurde und der Protokollbefehl in diesem Repository ausgeführt wurde. Ich denke, dass eine Bearbeitung in Ordnung ist ...
CB Bailey
"Festschreibungsdatum, das aktualisiert wird, wenn ein Festschreiben in irgendeiner Weise neu basiert oder geändert wird", tatsächlich wird das Datum nie geändert; Das gesamte Commit wird durch ein anderes Commit ersetzt (obwohl der Baum angeblich der gleiche sein könnte).
Hasen
2
@hasen j: Technisch gesehen hast du recht. Commits sind unveränderlich. Wenn Sie rebase oder ändern , eine Festschreibung und erstellen Sie eine neue begehen, begehen die bestehende Commit - Nachricht, Autor Details und Autor Datum oft von der alten kopiert werden , so ist es , wie Sie aktualisieren die mit einem neuen commit id begehen und das Datum begehen.
CB Bailey
Beachten Sie, dass die @{time spec}Syntax immer auf Ihr lokales Reflog verweist . Es bezieht sich nicht auf den tatsächlichen Commit-Verlauf (DAG). Wenn Sie den Unterschied nicht verstehen, verwenden Sie diese Syntax nicht!
Mikko Rantalainen
14
git diff --stat @{2013-11-01}..@{2013-11-30}

oder

git diff --stat @{2.weeks.ago}..@{last.week}
AA.
quelle
Kommt es auf das Reflog an? Wenn dies der Fall ist, können Sie dies nicht verwenden, wenn das Repo, in dem Sie diesen Befehl ausführen, neuer (dh frisch geklont) ist als der darin enthaltene Commit-Verlauf.
2
Ja, das hängt völlig vom Reflog ab. Und ja, dies funktioniert nur im lokalen Kopierverlauf, ist aber ein praktischer Befehl.
AA.
1
Ja, ich stimme definitiv zu, dass es praktisch ist, solange Sie Reflog-Einträge haben, die alt genug sind, um dies zu unterstützen.
Vielen Dank, AA. Mit Ihrer Antwort konnte ich Folgendes tun: git annotate --stat .. @ {2017-08-8} filename | weniger; git annotate --stat .. @ {5.days.ago} Dateiname; so kann ich die Änderungen im Kontext sehen.
Chris
Beachten Sie, dass die @{time spec}Syntax immer auf Ihr lokales Reflog verweist . Es bezieht sich nicht auf den tatsächlichen Commit-Verlauf (DAG). Wenn Sie den Unterschied nicht verstehen, verwenden Sie diese Syntax nicht!
Mikko Rantalainen
4

Vielleicht

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

ist was du willst (mit oder ohne '--stdout')?

Jakub Narębski
quelle
1
Kurze Frage: Verwendet - seit dem Festschreibungsdatum?
CB Bailey
3

Ich glaube, die allgemeine Lösung besteht darin, Folgendes zu verwenden:

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

Ohne --first-parent erhalten Sie möglicherweise ein Commit von einem Zweig, der später zusammengeführt wurde, a refaber noch nicht zusammengeführt wurdea date string .

Hier ist eine Alternative mit --childrenund grepanstelle von -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 ' '
}

Ich war git whatchangedvor dem Lesen dieser Fragen und Antworten nicht damit vertraut , aber es gibt sehr unterschiedliche Ergebnisse für mich, daher bin ich mir nicht sicher, was es tut.

Matt McClure
quelle
3

Eine andere einfache Möglichkeit, einen Unterschied aller Änderungen seit einem bestimmten Datum zu erhalten, besteht darin, einfach das erste Commit zu finden, Xdas an oder nach diesem Datum stattgefunden hat, und es dann zu verwenden

git diff X

Dies hat den Vorteil, dass es im Gegensatz zum nicht zu Reflog-Einträgen in einem neuen Klon kommt

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

Lösungen in

Gemeinschaft
quelle
2

Dies ist eher eine lustige Antwort, weil es wahrscheinlich einen besseren Weg gibt. Dies zeigt alle Commit-Hashes für heute.

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

; ·)

gahooa
quelle
2

Sie können auch den Git-Format-Patch verwenden , um Patches (Diffs) vorzubereiten und per E-Mail zu senden.

Verwenden Sie die Optionen [seit] oder [Revisionsbereich], um den Festschreibungsbereich anzugeben.

Nick Dandoulakis
quelle
2

Verwenden Sie die folgende Formel, um zu sehen, wie sich Git-Dateien in Ihrem Zweig von Datum zu Datum ändern :

  1. Kasse deine Filiale.
  2. Änderungen aus dem Remote-Repository abrufen und aktualisieren
  3. Beobachten Sie Diff-Dateien von Datum zu Datumsbereich

Formel :

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

Beachten Sie, dass die Daten im Format JJJJ-MM-TT vorliegen:

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

Wenn Sie Änderungen an einer bestimmten Datei in einem bestimmten Zeitraum beobachten möchten beobachten möchten (beobachten Sie den Unterschied im Code), navigieren Sie einfach in der aktuellen Datei:

Beispiel :

git diff @{2019-01-01}..@{2019-01-02} ~/dev/myApp/package.json
avivamg
quelle
0

Ich werde die Art und Weise einwerfen, wie ich es mache: git logFür ein Datum erhalten Sie Hashes für den aktuellen Zweig. Dann benutze ich einfach so etwas git diff 8fgdfg8..565k4l5, was mir den richtigen Unterschied gibt, der nach Dateien aggregiert ist. Hoffe das hilft, aber nicht viel getestet

rostamn739
quelle