git rebase senza modificare i timestamp di commit

Avrebbe senso eseguire git rebase preservando i timestamp di commit?

Credo che una conseguenza sarebbe che il nuovo ramo non avrà necessariamente date di scadenza in ordine cronologico. È teoricamente ansible? (ad esempio usando i comandi idraulici, solo curiosi qui)

Se è teoricamente ansible, allora è ansible in pratica con rebase, non cambiare i timestamp?

Ad esempio, supponiamo di avere il seguente albero:

 master  | : : : oldbranch  : / oldcommit  

Ora, se rebase oldbranch su master , la data del commit cambia da feb 1984 a jun 2010. È ansible modificare tale comportamento in modo che la data / ora di commit non venga cambiata? Alla fine otterrei così:

  oldbranch  / master  | : 

Avrebbe senso? E ‘anche permesso in git di avere una cronologia in cui un vecchio commit ha un commit più recente come genitore?

Aggiornamento giugno 2014: David Fraser menziona nei commenti una soluzione dettagliata anche in ” Modifica timestamp durante la ridefinizione del ramo git “, utilizzando l’opzione --committer-date-is-author-date (introdotta inizialmente nel gennaio 2009 in commit 3f01ad6

Si noti che l’ --committer-date-is-author-date sembra lasciare il timestamp dell’autore e impostare il timestamp del committer in modo che corrisponda al timestamp dell’autore originale, che è ciò che l’ OP Olivier Verdier voleva.

Ho trovato l’ultimo commit con la data corretta e ho fatto:

 git rebase --committer-date-is-author-date SHA 

Vedi git am :

 --committer-date-is-author-date 

Per impostazione predefinita, il comando registra la data dal messaggio di posta elettronica come data dell’autore del commit e utilizza l’ora di creazione del commit come data del commit.
Ciò consente all’utente di mentire sulla data del committer utilizzando lo stesso valore della data dell’autore .


(Risposta originale, giugno 2012)

Potresti provare, per un rebase non interattivo

 git rebase --ignore-date 

(da questa risposta SO )

Questo è passato a git am , che menziona:

  --ignore-date 

Per impostazione predefinita, il comando registra la data dal messaggio di posta elettronica come data dell’autore del commit e utilizza l’ora di creazione del commit come data del commit.
Ciò consente all’utente di mentire sulla data dell’autore utilizzando lo stesso valore della data del commit.

Per git rebase , questa opzione è “Incompatibile con l’opzione –interactive”.

Dato che puoi cambiare a piacimento il timestamp della vecchia data di commit (con git filter-branch ), suppongo che tu possa organizzare la tua cronologia di Git con qualsiasi ordine di data di commit tu voglia / abbia bisogno, anche impostandolo sul futuro! .


Come Olivier menziona nella sua domanda, la data dell’autore non viene mai modificata da un rebase;
Dal Pro Git Book :

  • L’autore è la persona che ha originariamente scritto l’opera,
  • mentre il committer è la persona che ha applicato per ultimo il lavoro.

Quindi, se si invia una patch a un progetto e uno dei membri principali applica la patch, entrambi ricevono credito.

Per essere più chiaro, in questo caso, come commenta Olivier:

il --ignore-date fa il contrario di quello che stavo cercando di ottenere !
Vale a dire, cancella il timestamp dell’autore e sostituiscilo con i timestamp dei commit!
Quindi la risposta giusta alla mia domanda è:
Non fare nulla, poiché git rebase realtà non modifica i timestamp degli autori per impostazione predefinita.


Se hai già rovinato le date di commit (magari con un rebase) e vuoi reimpostarle alle date dell’autore corrispondenti, puoi eseguire:

git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE'

Una questione cruciale di Von C mi ha aiutato a capire cosa sta succedendo: quando il rebase cambia, il timestamp del committer cambia, ma non il timestamp dell’autore , che improvvisamente ha tutto senso. Quindi la mia domanda non era in realtà abbastanza precisa.

La risposta è che rebase in realtà non cambia i timestamp dell’autore (non è necessario fare nulla per questo), che mi si addice perfettamente.

Per impostazione predefinita, git rebase imposterà il timestamp del committer al momento in cui viene creato il nuovo commit, ma mantiene intatto il timestamp dell’autore. La maggior parte del tempo, questo è il comportamento desiderato, ma in alcuni scenari, non puntiamo neanche a modificare il timestamp del committente. Come possiamo riuscirci? Bene, ecco il trucco che faccio di solito.

In primo luogo, assicurati che ciascuno dei commit che stai per rebase abbia un messaggio di commit univoco e un timestamp dell’autore (questo è il punto in cui il trucco ha bisogno di miglioramenti, al momento si adatta alle mie esigenze).

Prima del rebase, registra il timestamp del committer, il timestamp dell’autore e il messaggio di commit di tutti i commit che verranno ridefiniti in un file.

 #NOTE: BASE is the commit where your rebase begins git log --pretty='%ct %at %s' BASE..HEAD > hashlog 

Quindi, lasciare che il rebase effettivo abbia luogo.

Infine, sostituiamo il timestamp del commit corrente con quello registrato nel file se il messaggio di commit è lo stesso usando git filter-branch .

  git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%at %s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_COMMITTER_DATE=$__date || cat' 

Se qualcosa va storto, git reflog checkout git reflog o tutti i refs/original/ refs.

Furthormore, puoi fare la stessa cosa con il timestamp dell’autore.

Ad esempio, se il timestamp dell’autore di alcuni commit è fuori servizio e senza riorganizzare questi commit, vogliamo solo che il timestamp dell’autore venga mostrato in ordine, quindi i seguenti comandi aiuteranno.

 git log --pretty='%at %s' COMMIT1..COMMIT2 > hashlog join -1 1 -2 1 <(cat hashlog | cut -f 1 | sort -nr | awk '{ print NR" "$1 }') <(cat hashlog | awk '{ print NR" "$0 }') | cut -d" " -f2,4- > hashlog_ mv hashlog_ hashlog git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_AUTHOR_DATE=$__date || cat'