Come effettuare il checkout in Git per data?

Sto lavorando su una regressione nel codice sorgente. Vorrei dire a Git: “controlla la fonte in base a una data / ora parametrizzata”. È ansible?

Ho anche messo in scena cambiamenti nella mia attuale opinione che non voglio perdere. Idealmente, mi piacerebbe passare avanti e indietro tra la sorgente corrente e una versione a cui sono interessato in base a una data precedente.

Per mantenere le tue attuali modifiche

Puoi tenere il tuo lavoro nascosto, senza commetterlo, con git stash . Dovresti usare git stash pop per git stash pop . Oppure puoi (come ha detto carleeto ) git commit in un ramo separato.

Checkout per data usando rev-parse

Puoi eseguire il checkout di un commit in base a una data specifica usando rev-parse come questo:

 git checkout '[email protected]{1979-02-26 18:30:00}' 

Maggiori dettagli sulle opzioni disponibili sono disponibili nel git-rev-parse .

Come notato nei commenti, questo metodo usa il reflog per trovare il commit nella cronologia. Per impostazione predefinita, queste voci scadono dopo 90 giorni . Sebbene la syntax per usare il reflog sia meno dettagliata, puoi tornare indietro di 90 giorni.

Esegui il check out per data utilizzando l’elenco rev

L’altra opzione, che non usa il reflog, è quella di usare rev-list per ottenere il commit in un momento particolare con:

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

La soluzione di Andy non funziona per me. Qui ho trovato un altro modo:

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

Git: checkout per data

Sembra che tu abbia bisogno di qualcosa sulla falsariga di questo: Git checkout basato sulla data

In altre parole, usi rev-list per trovare il commit e poi usa checkout per ottenerlo.

Se non vuoi perdere i tuoi cambiamenti graduali, la cosa più semplice sarebbe creare un nuovo ramo e assegnarli a quel ramo. Puoi sempre passare avanti e indietro tra i rami.

Modifica: il collegamento è inattivo, quindi ecco il comando:

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

A coloro che preferiscono una pipa per comandare la sostituzione

 git rev-list -n1 --before=2013-7-4 master | xargs git checkout 

Nel mio caso l’opzione -n 1 non funziona. Su Windows ho trovato che la seguente sequenza di comandi funziona bene:

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

Ciò restituisce lo SHA del commit appropriato per la data specificata, quindi:

 git checkout SHA 

Andando oltre con l’opzione rev-list , se si desidera trovare il commit di fusione più recente dal ramo master nel ramo di produzione (come un esempio puramente ipotetico):

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

Avevo bisogno di trovare il codice che si trovava sui server di produzione a partire da una certa data. Questo l’ha trovato per me.

La soluzione git rev-parse proposta da @Andy funziona bene se la data che ti interessa è la data del commit . Se tuttavia si desidera effettuare il checkout in base alla data dell’autore , rev-parse non funzionerà, perché non offre un’opzione per utilizzare quella data per la selezione dei commit. Invece, puoi usare quanto segue.

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

(Se si desidera specificare anche il tempo, utilizzare $1 >= "2016-04-12" && $2 >= "11:37" nel predicato di awk .)

Se vuoi essere in grado di ritornare alla versione precisa del repository nel momento in cui fai una build, è meglio taggare il commit da cui fai la build.

Le altre risposte forniscono tecniche per restituire il repository al commit più recente in un ramo a partire da un certo periodo di tempo, ma potrebbero non sempre essere sufficienti. Ad esempio, se si costruisce da un ramo e successivamente si elimina il ramo, o si costruisce da un ramo che viene successivamente rebasato, il commit da cui è stato generato può diventare “irraggiungibile” in git da qualsiasi ramo corrente. Gli oggetti non raggiungibili in git possono eventualmente essere rimossi quando il repository viene compattato.

Mettere un tag sul commit significa che non diventa mai irraggiungibile, indipendentemente da ciò che fai con i rami in seguito (escludendo la rimozione del tag).

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

prendere la stringa stampata (ad esempio XXXX) e fare:

 git checkout XXXX