Come si può cambiare il timestamp di un vecchio commit in Git?


747

Le risposte a Come modificare i commit esistenti e non compressi? descrivere un modo per modificare i precedenti messaggi di commit che non sono stati ancora inviati a monte. I nuovi messaggi ereditano i timestamp dei commit originali. Sembra logico, ma c'è un modo per reimpostare anche i tempi?



34
git commit --amend --reset-author
Erick M. Sprengel,

Risposte:


536

Utilizzare git filter-branchcon un filtro env che imposta GIT_AUTHOR_DATEe GIT_COMMITTER_DATEper l'hash specifico del commit che si desidera correggere.

Ciò invaliderà questo e tutti gli hash futuri.

Esempio:

Se si desidera modificare le date di commit 119f9ecf58069b265ab22f1f97d2b648faf932e0, è possibile farlo con qualcosa del genere:

git filter-branch --env-filter \
    'if [ $GIT_COMMIT = 119f9ecf58069b265ab22f1f97d2b648faf932e0 ]
     then
         export GIT_AUTHOR_DATE="Fri Jan 2 21:38:53 2009 -0800"
         export GIT_COMMITTER_DATE="Sat May 19 01:01:01 2007 -0700"
     fi'


8
Ciò ha trovato il valore corretto, ma il solo fatto di impostare quelle variabili non sembra aver influito sulla data del vecchio commit.
IQAndreas,

36
Cosa intendi con "Questo invaliderà questo e tutti gli hash futuri."?
EpicDavi,

16
EpicDavi: significa che dovrai forzare il push verso qualsiasi repository remoto e chiunque abbia eseguito il commit o eventuali commit futuri dovrà reimpostare e pull, oppure eliminare e clonare da zero. Per quanto ne so, non esiste alcun metodo che aggiri questo.
EriF89,

4
Proprio come una nota per i principianti, l'hash breve non funziona
nell'istruzione

780

È possibile eseguire un rebase interattivo e scegliere la modifica per il commit di cui si desidera modificare la data. Quando il processo di rebase si interrompe per modificare il commit digitato ad esempio:

git commit --amend --date="Wed Feb 16 14:00 2011 +0100"

Successivamente si continua il rebase interattivo.

AGGIORNAMENTO (in risposta al commento di studgeek): per modificare la data di commit anziché la data dell'autore:

GIT_COMMITTER_DATE="Wed Feb 16 14:00 2011 +0100" git commit --amend

Le righe sopra impostano una variabile di ambiente GIT_COMMITTER_DATE che viene utilizzata nel commit di modifica.

Tutto è testato in Git Bash.


22
@nschum --date = "" e --data "non-data-text" producono tutti lo stesso, prendendo la data di adesso.
Paul Pladijs,

12
su git versione 1.7.7.1 usando --date = "now" restituisce fatale: formato data non valido: ora
Aragorn

4
Quando il commit di cui desideri modificare la data è il commit più recente, non devi eseguire il rebase, puoi semplicemente eseguiregit commit --amend
Eponymous

7
Invece di esportare GIT_COMMITTER_DATE = "", prova a disinserire GIT_COMMITTER_DATE.
Mark E. Haase,

2
Sto usando --no-edit in modo da poterlo usare negli script automatici! + var fixedDate = strftime(new Date(), "%c"); + var result = shelljs.exec("git commit --amend --date=\"" + fixedDate + "\" --no-edit");
Marcello de Sales,

392

Un modo migliore per gestire tutti questi suggerimenti in un solo comando è

LC_ALL=C GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"

Ciò imposterà la data dell'ultimo commit e dell'autore dell'ultimo commit su "adesso".


22
Funziona alla grande per modificare specifici commit durante un rebase interattivo.
friederbluemle,

2
Potresti aggiungere un alias alla shell anche per questo
kaleissin

14
Sembra che Git non sia a conoscenza delle LANG= GIT_COMMITTER_DATE="`date`" git commit --amend --date "`date`"
impostazioni

Lo faccio quando rifaccio e schiaccio un ramo, quindi crea un unico commit con un timestamp aggiornato.
Luke Ehresman,

12
puoi anche solo fare --date "now". Git> = 2 lo interpreterà.
Wisbucky

189

Fallo e basta git commit --amend --reset-author --no-edit. Per i commit più vecchi, è possibile effettuare un rebase interattivo e scegliere editper il commit la cui data si desidera modificare.

git rebase -i <ref>

Quindi modificare il commit con --reset-authore --no-editper modificare la data dell'autore alla data corrente:

git commit --amend --reset-author --no-edit

Infine continua con il tuo rebase interattivo:

git rebase --continue

5
buona chiamata per l'uso --reset-author, è nuovo in git 1.6.6 (ref gitlog.wordpress.com/2010/01/13/git-1-6-6 )
Tim Abell

1
Questo funziona bene per fare in modo che Github mostri i commit di una PR rinnovata nell'ordine corretto, dal momento che li ordinano per timestamp e senza questo trucco, i timestamp potrebbero essere tutti uguali.
Nathan Long

4
la nota --reset-authorripristinerà sia l'Autore che la Data dell'autore a ora.
Wisbucky

cambierà la "DATA COMMITTER" contemporaneamente?
luochen1990,

134

Ho scritto una sceneggiatura e un pacchetto Homebrew per questo. Super facile da installare, puoi trovarlo sulla PotatoLabs/git-redatepagina GitHub .

Sintassi:

git redate -c 3

Devi solo eseguire git redatee sarai in grado di modificare tutte le date in vista degli ultimi 5 commit (c'è anche -cun'opzione per quanti commit vuoi tornare indietro, il valore predefinito è 5). Fammi sapere se hai domande, commenti o suggerimenti!

inserisci qui la descrizione dell'immagine


2
Roba fantastica, anche se ho dovuto usare vim piuttosto che nano
howdoyouturnthison

Grazie @Edmund per l'ottima sceneggiatura. Non ho potuto vedere la data da modificare in vi dopo aver eseguito git redate -c. Tutto quello che vedo è% cI | XXXXXXXXXXXXXXXX | Impegno iniziale. Potresti aiutarmi, per favore? Grazie
Kiem Nguyen il

@KiemNguyen potresti provare semplicemente git redate (senza il -c)?
bigpotato,

4
completamente d'accordo con Mina e @howdoyouturnthison qui, perché non lo rendi editor agnostico tramite la variabile di ambiente EDITOR? (anche io sono su Linux, non su Mac ...)
ympostor,

3
Grazie @Edmund! Nel caso, lo script ha un problema con la gestione del valore predefinito per COMMITS. Se non è impostato, il codice seguente applica i filtri solo a (suppongo / trovato) l'ultimo commit. "git filter-branch -f --env-filter" $ ENVFILTER "HEAD ~ $ COMMITS..HEAD> / dev / null"
Grigory Entin

103

Ogni commit è associato a due date, la data del committer e la data dell'autore. Puoi visualizzare queste date con:

git log --format=fuller

Se vuoi cambiare la data dell'autore e la data del committer degli ultimi 6 commit, puoi semplicemente usare un rebase interattivo:

git rebase -i HEAD~6

.

pick c95a4b7 Modification 1
pick 1bc0b44 Modification 2
pick de19ad3 Modification 3
pick c110e7e Modification 4
pick 342256c Modification 5
pick 5108205 Modification 6

# Rebase eadedca..5108205 onto eadedca (6 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

Per tutti i commit in cui desideri modificare la data, sostituisci pickcon edit(o solo e), quindi salva ed esci dal tuo editor.

Ora puoi modificare ogni commit specificando la data dell'autore e la data del committer nel formato ISO-8601:

GIT_COMMITTER_DATE="2017-10-08T09:51:07" git commit --amend --date="2017-10-08T09:51:07"

La prima data è la data di commit, la seconda è la data dell'autore.

Quindi vai al prossimo commit con:

git rebase --continue

Ripeti il ​​processo fino a quando non modifichi tutti i tuoi commit. Controlla la tua progressione con git status.


1
Ho seguito questo e sono finito su una 'testa staccata'!
Simon H,

1
@Simon H Ho testato di nuovo la mia risposta e funziona bene. Avresti dovuto digitare qualcosa di diverso o eri già in una testa distaccata. Se vuoi tornare da una testa distaccata, fai un git checkout name-of-current-branch.
Ortomala Lokni,

4
Questa è la risposta migliore e più semplice. Piccolo consiglio: usa --no-edit in git commit --amend --no-edit --date=2017-10-08T09:51:07per conservare il vecchio messaggio di commit.
Mariusz Pawelski,

2
Potresti anche voler aggiornare GIT_COMMITTER_DATE come descritto qui eddmann.com/posts/…
smihael,

2
@smihael Grazie per il link. Ho incluso il tuo suggerimento nella mia risposta.
Ortomala Lokni,


44

Sulla theosp 's risposta , ho scritto uno script chiamato git-cdc(per la data cambiamento commit) che ho messo nel mio PATH.

Il nome è importante: git-xxxovunque nel tuo PATHti permette di digitare:

git xxx
# here
git cdc ... 

Quello script è in bash, anche su Windows (poiché Git lo chiamerà dal suo ambiente msys )

#!/bin/bash
# commit
# date YYYY-mm-dd HH:MM:SS

commit="$1" datecal="$2"
temp_branch="temp-rebasing-branch"
current_branch="$(git rev-parse --abbrev-ref HEAD)"

date_timestamp=$(date -d "$datecal" +%s)
date_r=$(date -R -d "$datecal")

if [[ -z "$commit" ]]; then
    exit 0
fi

git checkout -b "$temp_branch" "$commit"
GIT_COMMITTER_DATE="$date_timestamp" GIT_AUTHOR_DATE="$date_timestamp" git commit --amend --no-edit --date "$date_r"
git checkout "$current_branch"
git rebase  --autostash --committer-date-is-author-date "$commit" --onto "$temp_branch"
git branch -d "$temp_branch"

Con ciò, puoi digitare:

git cdc @~ "2014-07-04 20:32:45"

Ciò ripristinerebbe la data autore / commit del commit prima di HEAD ( @~) alla data specificata.

git cdc @~ "2 days ago"

Ciò ripristinerebbe la data autore / commit del commit prima di HEAD ( @~) alla stessa ora, ma 2 giorni fa.


Ilya Semenov menziona nei commenti :

Per OS X puoi anche installare GNU coreutils( brew install coreutils), aggiungerlo a PATH( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") e quindi usare la 2 days agosintassi " ".


1
Per me questo ha funzionato solo citando la data e l'ora in un'unica citazione: git cdc @~ "2014-07-04 20:32:45altrimenti non riconoscerebbe l'ora e quindi otterrebbe l'ora 00:00:00 (diventa il terzo argomento).
Peschü,

3
Per OS X puoi anche installare GNU coreutils ( brew install coreutils), aggiungerlo a PATH ( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") e quindi usare la sintassi "2 giorni fa".
Ilya Semenov,

1
@IlyaSemenov Interessante. Ho incluso il tuo commento nella risposta per una maggiore visibilità.
VonC,

Sto cercando di usare il tuo primo esempio ma continuo a ricevere "fatal: formato data non valido:". Quale formato di data si aspetta Mac OS X?
usbsnowcrash l'

@usbsnowcrash non è sicuro su Mac. Il secondo esempio " 2 days ago" funziona?
VonC,

25

Come modificare più date di commit

Altre risposte non sono molto utili per la modifica di più date di commit. Sono tornato a questa domanda dopo alcuni anni per condividere una tecnica.

Per modificare le date degli ultimi 4 commit:

git rebase -i HEAD~4

Modifica il rebase come segue, inserendo le execrighe per modificare le date secondo necessità:

pick 4ca564e Do something
exec git commit --amend --no-edit --date "1 Oct 2019 12:00:00 PDT"
pick 1670583 Add another thing
exec git commit --amend --no-edit --date "2 Oct 2019 12:00:00 PDT"
pick b54021c Add some tests
exec git commit --amend --no-edit --date "3 Oct 2019 12:00:00 PDT"
pick e8f6653 Fix the broken thing
exec git commit --amend --no-edit --date "4 Oct 2019 12:00:00 PDT"

Buon uso dell'opzione --amend/ --date. Più semplice della mia risposta usando le variabili di ambiente. Upvoted.
VonC,

È possibile utilizzare la data / ora corrente come parametro?
Accfews

GIT_AUTHOR_DATESolo aggiornamenti .
Blaise

Ri. 'È possibile utilizzare la data / ora corrente come parametro?': "Ora" è inteso come una data valida, quindi le righe exec sopra diventerebberoexec git commit --amend --no-edit --date "now"
Andrew Richards

20

se è l'ultimo commit precedente.

git rebase  -i HEAD~2
git commit --amend --date=now

se spingi già su originale e puoi forzare l'uso:

git push --force 

se non puoi forzare la spinta e se viene spinta, non puoi cambiare il commit! .


18

Ecco un comodo alias che cambia i tempi di commit e di autore dell'ultimo commit in un orario accettato da date --date:

[alias]
    cd = "!d=\"$(date -d \"$1\")\" && shift && GIT_COMMITTER_DATE=\"$d\" \
            git commit --amend --date \"$d\""

Uso: git cd <date_arg>

Esempi:

git cd now  # update the last commit time to current time
git cd '1 hour ago'  # set time to 1 hour ago

Modifica: ecco una versione più automatizzata che verifica che l'indice sia pulito (nessuna modifica non impegnata) e riutilizza l'ultimo messaggio di commit o non riesce altrimenti (a prova di errore):

[alias]
    cd = "!d=\"$(date -d \"$1\")\" && shift && \
        git diff-index --cached --quiet HEAD --ignore-submodules -- && \
        GIT_COMMITTER_DATE=\"$d\" git commit --amend -C HEAD --date \"$d\"" \
        || echo >&2 "error: date change failed: index not clean!"

17

Ho creato questo pacchetto npm per cambiare la data dei vecchi commit.

https://github.com/bitriddler/git-change-date

Esempio di utilizzo:

npm install -g git-change-date
cd [your-directory]
git-change-date

Ti verrà richiesto di scegliere il commit che desideri modificare, quindi inserire la nuova data.

Se si desidera modificare un commit mediante hash specifico, eseguire questo git-change-date --hash=[hash]


Volevo solo dire che è fantastico e ha funzionato magnificamente. Grazie, mi hai fatto risparmiare un sacco di tempo!
paranza,

17

La seguente funzione bash cambierà il tempo di qualsiasi commit sul ramo corrente.

Fare attenzione a non utilizzare se è già stato eseguito il push del commit o se si utilizza il commit in un altro ramo.

# rewrite_commit_date(commit, date_timestamp)
#
# !! Commit has to be on the current branch, and only on the current branch !!
# 
# Usage example:
#
# 1. Set commit 0c935403 date to now:
#
#   rewrite_commit_date 0c935403
#
# 2. Set commit 0c935403 date to 1402221655:
#
#   rewrite_commit_date 0c935403 1402221655
#
rewrite_commit_date () {
    local commit="$1" date_timestamp="$2"
    local date temp_branch="temp-rebasing-branch"
    local current_branch="$(git rev-parse --abbrev-ref HEAD)"

    if [[ -z "$date_timestamp" ]]; then
        date="$(date -R)"
    else
        date="$(date -R --date "@$date_timestamp")"
    fi

    git checkout -b "$temp_branch" "$commit"
    GIT_COMMITTER_DATE="$date" git commit --amend --date "$date"
    git checkout "$current_branch"
    git rebase "$commit" --onto "$temp_branch"
    git branch -d "$temp_branch"
}

1
Hai un bug qui: if [[ -z "$commit" ]]->if [[ -z "$date_timestamp" ]]
blueFast

Bello! Vorrei raccomandare l'impostazione GIT_COMMITTER_DATE=alla fine del metodo per evitare ulteriori impegni manuali per mantenere la data specificata.
loopkin,

@loopkin, GIT_COMMITTER_DATE è impostato solo per il comando "git commit", quindi non è necessario cancellarlo in seguito
nimrodm,

@nimrodm, ho appena provato di nuovo e hai ragione. Grazie per la segnalazione.
loopkin

12

Per modificare sia la data dell'autore che la data del commit:

GIT_COMMITTER_DATE="Wed Sep 23 9:40 2015 +0200" git commit --amend --date "Wed Sep 23 9:40 2015 +0200"

10

Se vuoi ottenere la data esatta di un altro commit (supponi di aver modificato un commit modificato e desideri che abbia la data della versione pre-rebase originale):

git commit --amend --date="$(git show -s --format=%ai a383243)"

Ciò corregge la data del commit HEAD in modo che sia esattamente la data del commit a383243 (includere più cifre se ci sono ambiguità). Apparirà anche una finestra dell'editor in modo da poter modificare il messaggio di commit.

Questo è per la data dell'autore che è ciò che ti interessa di solito - vedi altre risposte per la data del committer.


7

Se si desidera eseguire la risposta accettata ( https://stackoverflow.com/a/454750/72809 ) nella riga di comando standard di Windows, è necessario il comando seguente:

git filter-branch -f --env-filter "if [ $GIT_COMMIT = 578e6a450ff5318981367fe1f6f2390ce60ee045 ]; then export GIT_AUTHOR_DATE='2009-10-16T16:00+03:00'; export GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; fi"

Appunti:

  • Potrebbe essere possibile dividere il comando su più righe (Windows supporta la divisione delle linee con il simbolo del carret ^), ma non ci sono riuscito.
  • Puoi scrivere le date ISO, risparmiando molto tempo a trovare il giorno della settimana giusto e la frustrazione generale sull'ordine degli elementi.
  • Se vuoi che la data di Autore e Committer sia la stessa, puoi semplicemente fare riferimento alla variabile precedentemente impostata.

Mille grazie a un post sul blog di Colin Svingen . Anche se il suo codice non ha funzionato per me, mi ha aiutato a trovare la soluzione corretta.


7

Se il commit non è stato ancora inviato, posso usare qualcosa del genere:

git commit --amend --date=" Wed Mar 25 10:05:44 2020 +0300"

dopo che git bash apre l'editor con la data già applicata, quindi è sufficiente salvarlo digitando la modalità di comando dell'editor VI ": wq" e puoi spingerlo


2
Basta aggiungere alla bella risposta: se non si desidera modificare il messaggio di commit (se si desidera solo cambiare la data di commit), utilizzare l' --no-editopzione.
Antonio Vinicius Menezes Medei il

Inoltre, se il commit è già stato inviato, è comunque possibile inviare il commit modificato utilizzando git push -f(aggiornamento forzato). Ciò potrebbe avere effetti collaterali, però. (specialmente se molte persone hanno cloni locali del repository)
Antonio Vinicius Menezes Medei


2

Ci sono già molte risposte fantastiche, ma quando voglio cambiare la data per più commit in un giorno o in un mese, non trovo una risposta adeguata. Quindi creo una nuova sceneggiatura per questo con una spiegazione, spero che possa aiutare qualcuno:

#!/bin/bash

# change GIT_AUTHOR_DATE for commit at Thu Sep 14 13:39:41 2017 +0800
# you can change the data_match to change all commits at any date, one day or one month
# you can also do the same for GIT_COMMITTER_DATE

git filter-branch --force --env-filter '

date_match="^Thu, 14 Sep 2017 13+"              

# GIT_AUTHOR_DATE will be @1505367581 +0800, Git internal format 
author_data=$GIT_AUTHOR_DATE;                   
author_data=${author_data#@}                  
author_data=${author_data% +0800}                # author_data is 1505367581     

oneday=$((24*60*60))

# author_data_str will be "Thu, 14 Sep 2017 13:39:41 +0800", RFC2822 format
author_data_str=`date -R -d @$author_data`      

if [[ $author_data_str =~ $date_match ]];
then
    # remove one day from author_data
    new_data_sec=$(($author_data-$oneday))
    # change to git internal format based on new_data_sec
    new_data="@$new_data_sec +0800"             
    export GIT_AUTHOR_DATE="$new_data"
fi
' --tag-name-filter cat -- --branches --tags

La data verrà modificata:

AuthorDate: Wed Sep 13 13:39:41 2017 +0800
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.