Jak dokonać płatności w Git według daty?

314

Pracuję nad regresją w kodzie źródłowym. Chciałbym powiedzieć Gitowi: „sprawdź źródło na podstawie sparametryzowanej daty / godziny”. czy to możliwe?

Wprowadziłem także zmiany w moim obecnym widoku, których nie chcę stracić. Idealnie chciałbym przełączać się między bieżącym źródłem a niektórymi wersjami, które mnie interesują na podstawie poprzedniej daty.

Amir Afghani
źródło
9
Na wypadek, gdybyś o tym nie wiedział, git bisect świetnie nadaje się do wyszukiwania regresji. Powiedziałbym, użyj składni {1 rok temu}, jak powiedział Andy, aby znaleźć znane dobre zatwierdzenie, a następnie użyj tego jako git bisect goodpunktu początkowego .
MatrixFrog,
Wydaje mi się, że jest to dobry przypadek użycia tags.
Jess

Odpowiedzi:

365

Aby zachować bieżące zmiany

Możesz trzymać swoją pracę w ukryciu, bez angażowania się w nią git stash. Byś niż stosowanie git stash popgo odzyskać. Lub możesz (jak powiedział carleeto ) git commitdo osobnego oddziału.

Kasa według daty przy użyciu analizy składni

Możesz sprawdzić zatwierdzenie przed określoną datą, używając rev-parsenastępującego:

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

Więcej informacji na temat dostępnych opcji można znaleźć w git-rev-parse.

Jak zauważono w komentarzach, ta metoda używa refloga do znalezienia zatwierdzenia w twojej historii. Domyślnie wpisy te wygasają po 90 dniach . Chociaż składnia użycia reflogu jest mniej szczegółowa, możesz cofnąć się tylko o 90 dni.

Kasa według daty przy użyciu rev-list

Inną opcją, która nie korzysta z reflog, jest użycie, rev-listaby uzyskać zatwierdzenie w określonym momencie za pomocą:

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

Zwróć uwagę na --first-parent, jeśli chcesz tylko swoją historię, a nie wersje wprowadzone przez scalenie. Tego zwykle chcesz.

Andy
źródło
2
@Rocky Czy możesz podać nam więcej szczegółów Rocky? Co wpisujesz w wierszu poleceń i dlaczego mówisz, że to nie działa? Czy pojawia się komunikat o błędzie?
Andy,
8
@Rocky: Problem polega na tym, że parametr musi być ujęty w cudzysłów, w przeciwnym razie bash rozdziela argumenty w spacjach. Spróbować git co 'master@{2 days ago}'.
Mark Wilden
13
Uwaga: w zależności od tego, jak daleko się cofniesz, może to nie działać, ponieważ używa reflogu (który wygasa po pewnym czasie). Zobaczysz „ostrzeżenie: Dziennik dla„ wzorca ”wraca tylko do ...”. Rozwiązanie Rocky'ego zawsze będzie działać. git checkoutgit rev-list -n 1 --before="2009-07-27 13:37" master
Mark Nadig
3
Zredagowałem twoją odpowiedź, ponieważ backticks są przestarzałe i trudne do odczytania. Preferowane $(...)są podpowłoki .
Amedee Van Gasse
1
@ Andy Happy 40th birthday, Andy! (zakładając, że właśnie to miał na myśli 1979-02-26 :))
David Blevins
123

Rozwiązanie Andy'ego nie działa dla mnie. Tutaj znalazłem inny sposób:

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

Git: zamówienie według daty

Skalisty
źródło
3
Kiedy wykonuję powyższe polecenie, mam error: unknown switch `n'jakieś pomysły, jak to obejść?
Tim
15

Wygląda na to, że potrzebujesz czegoś takiego: Git Checkout na podstawie daty

Innymi słowy, używasz rev-listdo znalezienia zatwierdzenia, a następnie używasz kasy, aby go faktycznie pobrać.

Jeśli nie chcesz stracić wprowadzonych zmian, najłatwiej byłoby utworzyć nowy oddział i zatwierdzić go w tym oddziale. Zawsze możesz przełączać się między gałęziami.

Edycja: link nie działa, więc oto polecenie:

git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`
Carl
źródło
2
Świetny link! git checkout branch@{date}Przestaje więc działać po wylogowaniu, ale możesz użyć git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`.
cdunn2001
10

Dla tych, którzy wolą potok zamiast polecenia

git rev-list -n1 --before=2013-7-4 master | xargs git checkout
Steven Penny
źródło
9

W moim przypadku -n 1opcja nie działa. W systemie Windows stwierdziłem, że następująca sekwencja poleceń działa dobrze:

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

Zwraca SHA odpowiedniego zatwierdzenia dla podanej daty, a następnie:

git checkout SHA
BartoszKP
źródło
4

git rev-parseProponowany przez @Andy rozwiązanie działa dobrze jeżeli data jesteś zainteresowany jest popełnić data . Jeśli jednak chcesz dokonać transakcji na podstawie daty autora , rev-parsenie będzie działać, ponieważ nie oferuje opcji użycia tej daty do wyboru zatwierdzeń. Zamiast tego możesz użyć następujących.

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

(Jeśli chcesz również określić czas wykorzystania $1 >= "2016-04-12" && $2 >= "11:37"w predykacie awk ).

Diomidis Spinellis
źródło
3

Idąc dalej z tą rev-listopcją, jeśli chcesz znaleźć najnowsze zatwierdzenie scalania z gałęzi master do gałęzi produkcyjnej (jako czysto hipotetyczny przykład):

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

Musiałem znaleźć kod, który był na serwerach produkcyjnych na dany dzień. Znalazłem to dla mnie.

egerlach
źródło
2

Jeśli chcesz mieć możliwość powrotu do dokładnej wersji repozytorium w momencie wykonywania kompilacji, najlepiej oznaczyć zatwierdzenie, z którego wykonujesz kompilację.

Inne odpowiedzi dostarczają techniki przywracania repozytorium do ostatniego zatwierdzenia w gałęzi od określonego czasu - ale nie zawsze mogą one wystarczyć. Na przykład, jeśli budujesz z gałęzi, a później usuwasz gałąź lub budujesz z gałęzi, która później jest ponownie bazowana, zatwierdzenie, z którego zbudowałeś, może stać się „nieosiągalne” w git z dowolnej gałęzi. Nieosiągalne obiekty w git mogą zostać ostatecznie usunięte po skompaktowaniu repozytorium.

Umieszczenie znacznika na zatwierdzeniu oznacza, że ​​nigdy nie będzie ono nieosiągalne, bez względu na to, co zrobisz z gałęziami później (z wyjątkiem usuwania znacznika).

antlersoft
źródło
Chociaż nie daje mi to odpowiedzi, której szukam, zasługuje na dobrą wzmiankę za wskazanie aspektu, o którym nie wspomniano do tej pory. Może to być przyczyną problemów, które uniemożliwiają osiągnięcie właściwej wersji.
manuelvigarcia
1
git rev-list -n 1 --before="2009-07-27 13:37" origin/master

weź wydrukowany ciąg (na przykład XXXX) i wykonaj:

git checkout XXXX
Luca C.
źródło
2
Czy to nie jest duplikat odpowiedzi @bartoszkp? tylko dodanie odniesienia do pochodzenia powinno być komentarzem do drugiej odpowiedzi ...
manuelvigarcia
tak, właściwie prawie, po prostu wyjaśniając, co skopiować, kto nie wie, czym jest SHA (jak ja), w moim przypadku ten tekst był niejasny i to jest mój kod po znalezieniu rozwiązania, nie skopiowany, w rzeczywistości widać opcje też są nieco inne
Luca C.