Wie checke ich in Git nach Datum aus?

314

Ich arbeite an einer Regression im Quellcode. Ich möchte Git sagen: "Überprüfen Sie die Quelle anhand eines parametrisierten Datums / einer parametrisierten Uhrzeit". Ist das möglich?

Ich habe auch Änderungen in meiner aktuellen Ansicht vorgenommen, die ich nicht verlieren möchte. Im Idealfall möchte ich zwischen der aktuellen Quelle und einer Version, an der ich interessiert bin, basierend auf einem früheren Datum hin und her wechseln.

Amir Afghani
quelle
9
Nur für den Fall, dass Sie nichts darüber wissen, ist Git Bisect ziemlich gut geeignet , um Regressionen zu finden. Ich würde sagen, verwenden Sie die Syntax {vor 1 Jahr}, wie Andy sagte, um ein bekanntermaßen gutes Commit zu finden, und verwenden Sie diese dann als Ausgangspunkt git bisect good.
MatrixFrog
Ich denke, dies ist ein guter Anwendungsfall für tags.
Jess

Antworten:

365

Um Ihre aktuellen Änderungen beizubehalten

Sie können Ihre Arbeit verstauen, ohne sie zu verpflichten git stash. Sie würden es dann verwenden git stash pop, um es zurückzubekommen. Oder Sie können es (wie Carleeto sagte) git commitzu einem separaten Zweig.

Kaufabwicklung nach Datum mit rev-parse

Sie können ein Commit bis zu einem bestimmten Datum rev-parsewie folgt auschecken :

git checkout 'master@{1979-02-26 18:30:00}'

Weitere Details zu den verfügbaren Optionen finden Sie in der git-rev-parse.

Wie in den Kommentaren erwähnt, verwendet diese Methode das Reflog, um das Commit in Ihrem Verlauf zu finden. Standardmäßig verfallen diese Einträge nach 90 Tagen . Obwohl die Syntax für die Verwendung des Reflogs weniger ausführlich ist, können Sie nur 90 Tage zurückgehen.

Checkout nach Datum mit Rev-Liste

Die andere Option, bei der das Reflog nicht verwendet wird, besteht rev-listdarin, das Commit zu einem bestimmten Zeitpunkt abzurufen mit:

git checkout `git rev-list -n 1 --first-parent --before="2009-07-27 13:37" master`

Beachten Sie das --first-parent, wenn Sie nur Ihren Verlauf und keine durch Zusammenführung eingebrachten Versionen möchten. Das ist es, was du normalerweise willst.

Andy
quelle
2
@Rocky Kannst du uns mehr Details geben Rocky? Was geben Sie in der Befehlszeile ein und warum funktioniert es nicht? Erhalten Sie eine Fehlermeldung?
Andy
8
@Rocky: Das Problem ist, dass der Parameter in Anführungszeichen gesetzt werden muss, andernfalls trennt bash die Argumente an Leerzeichen. Versuchen Sie es git co 'master@{2 days ago}'.
Mark Wilden
13
Hinweis: Je nachdem, wie weit Sie zurückgehen, funktioniert dies möglicherweise nicht, da das Reflog verwendet wird (das nach einiger Zeit abläuft). Sie sehen 'Warnung: Protokoll für' Master 'geht nur zurück zu ...'. Rockys Lösung wird immer funktionieren. Git Checkoutgit rev-list -n 1 --before="2009-07-27 13:37" master
Mark Nadig
3
Ich habe Ihre Antwort bearbeitet, da Backticks veraltet und schwer zu lesen sind. Unterschalen $(...)sind bevorzugt.
Amedee Van Gasse
1
@ Andy Alles Gute zum 40. Geburtstag, Andy! (vorausgesetzt, das war es, was der 26.02.1979 bedeutete :))
David Blevins
123

Andys Lösung funktioniert bei mir nicht. Hier habe ich einen anderen Weg gefunden:

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`

Git: Checkout nach Datum

Felsig
quelle
3
Wenn ich den obigen Befehl ausführe, bekomme ich error: unknown switch `n'Ideen, wie ich das umgehen kann?
Tim
15

Sieht so aus, als ob Sie etwas in dieser Richtung brauchen: Git-Checkout basierend auf dem Datum

Mit anderen Worten, Sie verwenden rev-listdas Commit und verwenden dann die Kasse, um es tatsächlich abzurufen.

Wenn Sie Ihre bereitgestellten Änderungen nicht verlieren möchten, ist es am einfachsten, einen neuen Zweig zu erstellen und ihn diesem Zweig zuzuweisen. Sie können jederzeit zwischen Zweigen hin und her wechseln.

Bearbeiten: Der Link ist ausgefallen, daher hier der Befehl:

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`
Carl
quelle
2
Toller Link! Funktioniert also nicht mehr git checkout branch@{date}, wenn das Reflog abläuft, aber Sie können es verwenden git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`.
cdunn2001
10

Für diejenigen, die eine Pipe bevorzugen, um die Substitution zu befehlen

git rev-list -n1 --before=2013-7-4 master | xargs git checkout
Steven Penny
quelle
9

In meinem Fall -n 1funktioniert die Option nicht. Unter Windows habe ich festgestellt, dass die folgende Befehlsfolge einwandfrei funktioniert:

git rev-list -1 --before="2012-01-15 12:00" master

Dies gibt die SHA des entsprechenden Commits für das angegebene Datum zurück und dann:

git checkout SHA
BartoszKP
quelle
4

Die git rev-parsevon @Andy vorgeschlagene Lösung funktioniert einwandfrei, wenn das Datum, an dem Sie interessiert sind , das Datum des Commits ist . Wenn jedoch mögen , dass Sie auf der Basis zur Kasse Autor Datum , rev-parsewird nicht funktionieren, weil sie über keine Möglichkeit bieten, dieses Datum zu verwenden , um die Commits zur Auswahl. Stattdessen können Sie Folgendes verwenden.

git checkout $(
  git log --reverse --author-date-order --pretty=format:'%ai %H' master |
  awk '{hash = $4} $1 >= "2016-04-12" {print hash; exit 0 }
)

(Wenn Sie auch die Zeitverwendung $1 >= "2016-04-12" && $2 >= "11:37"im awk- Prädikat angeben möchten .)

Diomidis Spinellis
quelle
3

Fahren Sie mit der rev-listOption fort, wenn Sie das letzte Zusammenführungs-Commit von Ihrem Hauptzweig in Ihren Produktionszweig finden möchten (als rein hypothetisches Beispiel):

git checkout `git rev-list -n 1 --merges --first-parent --before="2012-01-01" production`

Ich musste den Code finden, der sich zu einem bestimmten Datum auf den Produktionsservern befand. Das hat es für mich gefunden.

egerlach
quelle
2

Wenn Sie zum Zeitpunkt der Erstellung eines Builds zur genauen Version des Repositorys zurückkehren möchten, markieren Sie am besten das Commit, aus dem Sie den Build erstellen.

Die anderen Antworten bieten Techniken, mit denen das Repository zu einem bestimmten Zeitpunkt auf das letzte Commit in einem Zweig zurückgesetzt werden kann - sie reichen jedoch möglicherweise nicht immer aus. Wenn Sie beispielsweise aus einem Zweig erstellen und den Zweig später löschen oder aus einem Zweig erstellen, der später neu basiert, kann das Commit, aus dem Sie erstellt haben, in Git von jedem aktuellen Zweig aus "nicht erreichbar" werden. Nicht erreichbare Objekte in Git werden möglicherweise entfernt, wenn das Repository komprimiert wird.

Wenn Sie ein Tag auf das Commit setzen, wird es nie unerreichbar, unabhängig davon, was Sie anschließend mit Zweigen tun (außer das Entfernen des Tags).

Antlersoft
quelle
Obwohl dies nicht die Antwort gibt, nach der ich suche, verdient es eine gute Erwähnung, um auf einen Aspekt hinzuweisen, der bisher nicht erwähnt wurde. Dies könnte die Ursache für Probleme sein, die Sie daran hindern, die richtige Version zu erreichen.
Manuelvigarcia
1
git rev-list -n 1 --before="2009-07-27 13:37" origin/master

Nehmen Sie die gedruckte Zeichenfolge (zum Beispiel XXXX) und tun Sie Folgendes:

git checkout XXXX
Luca C.
quelle
2
Ist das nicht ein Duplikat der Antwort von @bartoszkp? Nur den Verweis auf Herkunft hinzufügen, sollte ein Kommentar zu der anderen Antwort sein ...
Manuelvigarcia
Ja, in der Tat fast, nur klarstellen, was kopiert werden soll, wer nicht weiß, was SHA ist (wie ich), in meinem Fall war dieser Text nicht klar und dies ist mein Code nach der Gründung der Lösung, nicht kopiert, in der Tat können Sie sehen Die Optionen sind auch etwas anders
Luca C.