Wie kann man den Zeitstempel eines alten Commits in Git ändern?


747

Die Antworten zu Wie ändere ich vorhandene, nicht gepuschte Commits? Beschreiben einer Möglichkeit zum Ändern früherer Commit-Nachrichten, die noch nicht in den Upstream verschoben wurden. Die neuen Nachrichten erben die Zeitstempel der ursprünglichen Commits. Dies scheint logisch, aber gibt es eine Möglichkeit, auch die Zeiten neu einzustellen?



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

Antworten:


535

Verwendung git filter-branchmit einem env Filter, die Sätze GIT_AUTHOR_DATEund GIT_COMMITTER_DATEfür den speziellen Hash - Wert des begehen Sie schauen , um fix.

Dies macht das und alle zukünftigen Hashes ungültig.

Beispiel:

Wenn Sie die ändern wollten Daten von begehen 119f9ecf58069b265ab22f1f97d2b648faf932e0, könnten Sie tun so etwas wie folgt aus :

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
Das hat den richtigen Wert gefunden, aber das Festlegen dieser Variablen schien das Datum des alten Commits nicht wirklich zu beeinflussen.
IQAndreas

36
Was meinst du mit "Dies wird das und alle zukünftigen Hashes ungültig machen."?
EpicDavi

16
EpicDavi: Dies bedeutet, dass Sie einen Push in ein Remote-Repository erzwingen müssen und jeder, der das Commit oder zukünftige Commits gezogen hat, zurücksetzen und ziehen oder löschen und von Grund auf neu klonen muss. Soweit ich weiß, gibt es keine Methode, um dies zu umgehen.
EriF89

4
Nur als Hinweis für Anfänger, funktioniert der kurze Hash nicht in der if-Anweisung, verwenden Sie die lange SHA-1
40detectives

780

Sie können eine interaktive Rebase durchführen und Bearbeiten für das Commit auswählen , dessen Datum Sie ändern möchten. Wenn der Rebase-Prozess zum Ändern des festgeschriebenen Commits beendet wird, geben Sie beispielsweise Folgendes ein:

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

Anschließend setzen Sie Ihre interaktive Rebase fort.

UPDATE (als Antwort auf den Kommentar von studgeek): um das Festschreibungsdatum anstelle des Autorendatums zu ändern:

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

In den obigen Zeilen wird eine Umgebungsvariable GIT_COMMITTER_DATE festgelegt, die beim Ändern des Commits verwendet wird.

Alles wird in Git Bash getestet.


22
@nschum --date = "" und --data "non-date-text" ergeben alle das gleiche Datum.
Paul Pladijs

12
auf Git Version 1.7.7.1 mit --date = "now" ergibt fatal: ungültiges Datumsformat: now
Aragorn

4
Wenn das Commit, dessen Datum Sie ändern möchten, das letzte Commit ist, müssen Sie das nicht tun rebase, Sie können einfach dasgit commit --amend
gleichnamige

7
Versuchen Sie, anstatt GIT_COMMITTER_DATE = "" zu exportieren, GIT_COMMITTER_DATE zu deaktivieren.
Mark E. Haase

2
Ich verwende --no-edit, damit Sie es in automatisierten Skripten verwenden können! + var fixedDate = strftime(new Date(), "%c"); + var result = shelljs.exec("git commit --amend --date=\"" + fixedDate + "\" --no-edit");
Marcello de Sales

392

Eine bessere Möglichkeit, alle diese Vorschläge in einem Befehl zu verarbeiten, ist

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

Dadurch werden das Festschreibungs- und Autorendatum des letzten Commits auf "jetzt" gesetzt.


22
Dies funktioniert hervorragend, um bestimmte Commits während einer interaktiven Rebase zu bearbeiten.
Friederbluemle

2
Sie können der Shell auch einen Alias ​​hinzufügen
Kaleissin

14
Es scheint, dass Git das Datumsformat nicht kennt. Um ganz richtig zu sein, müssen Sie es so machen:LANG= GIT_COMMITTER_DATE="`date`" git commit --amend --date "`date`"
Michał Góral

Ich mache das, wenn ich einen Zweig neu basiere und quetsche, so dass ein einzelnes Commit mit einem aktualisierten Zeitstempel erstellt wird.
Luke Ehresman

12
Sie können auch einfach tun --date "now". Git> = 2 wird das interpretieren.
wisbucky

189

Tu es einfach git commit --amend --reset-author --no-edit. Bei älteren Commits können Sie eine interaktive Rebase durchführen und editdas Commit auswählen , dessen Datum Sie ändern möchten.

git rebase -i <ref>

Ändern Sie dann das Commit mit --reset-authorund --no-edit, um das Autorendatum auf das aktuelle Datum zu ändern:

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

Fahren Sie abschließend mit Ihrer interaktiven Rebase fort:

git rebase --continue

5
Guter Aufruf zur Verwendung --reset-author, es ist neu in Git 1.6.6 (ref gitlog.wordpress.com/2010/01/13/git-1-6-6 )
Tim Abell

1
Dies funktioniert gut, damit Github die Commits einer neu basierten PR in der richtigen Reihenfolge anzeigt, da sie nach Zeitstempel sortiert sind und ohne diesen Trick die Zeitstempel möglicherweise alle gleich sind.
Nathan Long

4
note --reset-authorsetzt sowohl den Autor als auch das Autorendatum auf jetzt zurück.
wisbucky

Wird dies gleichzeitig das "COMMITTER DATE" ändern?
luochen1990

134

Ich habe dafür ein Skript und ein Homebrew-Paket geschrieben. Super einfach zu installieren, finden Sie es auf der GitHub- PotatoLabs/git-redateSeite.

Syntax:

git redate -c 3

Sie müssen nur ausgeführt werden git redateund können alle Daten in den letzten 5 Commits bearbeiten (es gibt auch eine -cOption für die Anzahl der Commits, die Sie zurückgehen möchten, standardmäßig 5). Lassen Sie mich wissen, wenn Sie Fragen, Kommentare oder Vorschläge haben!

Geben Sie hier die Bildbeschreibung ein


2
Tolles Zeug, obwohl ich lieber Vim als Nano verwenden musste
howdoyouturnthison

Danke @Edmund für ein tolles Skript. Ich konnte das zu bearbeitende Datum in vi nicht sehen, nachdem ich git redate -c ausgeführt hatte. Ich sehe nur% cI | XXXXXXXXXXXXXXXXX | Erstes Festschreiben. Kannst du bitte helfen? Vielen Dank
Kiem Nguyen

@KiemNguyen könntest du versuchen, git redate (ohne das -c)?
Bigpotato

4
Stimmen Sie hier vollständig mit Mina und @howdoyouturnthison überein. Warum machen Sie den Editor nicht über die Umgebungsvariable EDITOR unabhängig? (auch ich bin auf Linux, nicht Mac ...)
ympostor

3
Danke @Edmund! Nur für den Fall, dass Ihr Skript ein Problem mit der Behandlung des Standardwerts für COMMITS hat. Wenn es nicht gesetzt ist, wendet der folgende Code Filter nur auf (ich denke / gefunden) das letzte Commit an. "git filter-branch -f --env-filter" $ ENVFILTER "HEAD ~ $ COMMITS..HEAD> / dev / null"
Grigory Entin

102

Jedes Commit ist mit zwei Daten verknüpft, dem Committer-Datum und dem Autorendatum. Sie können diese Daten anzeigen mit:

git log --format=fuller

Wenn Sie das Autorendatum und das Committer-Datum der letzten 6 Commits ändern möchten, können Sie einfach eine interaktive Rebase verwenden:

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

Ersetzen Sie für alle Commits, bei denen Sie das Datum ändern möchten, pickdurch edit(oder nur e), speichern Sie den Editor und beenden Sie ihn.

Sie können jetzt jedes Commit ändern, indem Sie das Autorendatum und das Committerdatum im ISO-8601-Format angeben:

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

Das erste Datum ist das Festschreibungsdatum, das zweite das Autorendatum.

Fahren Sie dann mit dem nächsten Commit fort mit:

git rebase --continue

Wiederholen Sie den Vorgang, bis Sie alle Ihre Commits geändert haben. Überprüfen Sie Ihren Fortschritt mit git status.


1
Ich folgte dem und landete auf einem "entkoppelten Kopf"!
Simon H

1
@ Simon H Ich habe meine Antwort erneut getestet und es funktioniert gut. Sie hätten etwas anderes tippen sollen oder waren bereits in einem abgetrennten Kopf. Wenn Sie von einem abgetrennten Kopf zurückkommen möchten, tun Sie a git checkout name-of-current-branch.
Ortomala Lokni

3
Dies ist die beste und einfachste Antwort. Kleiner Tipp: Verwenden Sie --no-edit in git commit --amend --no-edit --date=2017-10-08T09:51:07, um die alte Festschreibungsnachricht beizubehalten.
Mariusz Pawelski

2
Vielleicht möchten Sie auch GIT_COMMITTER_DATE wie hier beschrieben aktualisieren eddmann.com/posts/…
smihael

2
@smihael Danke für den Link. Ich habe Ihren Vorschlag in meine Antwort aufgenommen.
Ortomala Lokni


44

Aufbauend auf der Antwort von theosp habe ich ein Skript mit dem Namen (für das Festschreiben des Änderungsdatums) geschrieben, das ich in mein Skript eingefügt habe .git-cdcPATH

Der Name ist wichtig: An git-xxxjeder Stelle in Ihrem PATHkönnen Sie Folgendes eingeben:

git xxx
# here
git cdc ... 

Dieses Skript ist in Bash, sogar unter Windows (da Git es aus seiner msys-Umgebung aufruft )

#!/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"

Damit können Sie Folgendes eingeben:

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

Dies würde das Autor / Commit-Datum des Commits vor HEAD ( @~) auf das angegebene Datum zurücksetzen .

git cdc @~ "2 days ago"

Das würde das Autor / Commit-Datum des Commits vor HEAD ( @~) auf dieselbe Stunde zurücksetzen , jedoch vor 2 Tagen.


Ilya Semenov erwähnt in den Kommentaren :

Für OS X können Sie auch GNU installieren coreutils( brew install coreutils), fügen Sie es PATH( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") und dann „verwenden 2 days ago“ Syntax.


1
Für mich funktionierte dies nur mit der Angabe von Datum und Uhrzeit in einem Zitat: git cdc @~ "2014-07-04 20:32:45Andernfalls würde es die Uhrzeit nicht erkennen und somit die Uhrzeit 00:00:00 erhalten (dies wird das dritte Argument).
Peschü

3
Unter OS X können Sie auch GNU coreutils ( brew install coreutils) installieren , es zu PATH ( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") hinzufügen und dann die Syntax "vor 2 Tagen" verwenden.
Ilya Semenov

1
@IlyaSemenov Interessant. Ich habe Ihren Kommentar zur besseren Sichtbarkeit in die Antwort aufgenommen.
VonC

Ich versuche, Ihr erstes Beispiel zu verwenden, erhalte jedoch immer wieder "fatal: ungültiges Datumsformat:". Welches Datumsformat erwartet Mac OS X?
usbsnowcrash

@usbsnowcrash nicht sicher auf Mac. Funktioniert das zweite Beispiel " 2 days ago"?
VonC

25

So bearbeiten Sie mehrere Festschreibungsdaten

Andere Antworten sind nicht sehr praktisch, um mehrere Festschreibungsdaten zu bearbeiten. Ich bin nach einigen Jahren auf diese Frage zurückgekommen, um eine Technik zu teilen.

So ändern Sie die Daten der letzten 4 Commits:

git rebase -i HEAD~4

Bearbeiten Sie die Rebase wie folgt und fügen Sie execZeilen ein, um die Daten nach Bedarf zu ändern:

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"

Gute Verwendung der Option --amend/ --date. Einfacher als meine eigene Antwort mit Umgebungsvariablen. Upvoted.
VonC

Ist es möglich, aktuelles Datum / Uhrzeit als Parameter zu verwenden?
Accfews

Das wird GIT_AUTHOR_DATEnur aktualisiert .
Blaise

Re. 'Ist es möglich, das aktuelle Datum / die aktuelle Uhrzeit als Parameter zu verwenden?': "Jetzt" wird als gültiges Datum verstanden, daher werden die obigen Ausführungszeilenexec git commit --amend --no-edit --date "now"
Andrew Richards

20

Wenn es das letzte Commit ist.

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

Wenn Sie bereits auf Orgin drücken und die Verwendung erzwingen können:

git push --force 

Wenn Sie den Push nicht erzwingen können und wenn er gedrückt wird, können Sie das Commit nicht ändern! .


18

Hier ist ein praktischer Alias, der sowohl die Festschreibungs- als auch die Autorenzeit der letzten Festschreibung in eine Zeit ändert, die akzeptiert wird von date --date:

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

Verwendungszweck: git cd <date_arg>

Beispiele:

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

Bearbeiten: Hier ist eine automatisiertere Version, die überprüft, ob der Index sauber ist (keine nicht festgeschriebenen Änderungen) und die letzte Festschreibungsnachricht wiederverwendet oder anderweitig fehlschlägt (narrensicher):

[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

Ich habe dieses npm-Paket erstellt, um das Datum alter Commits zu ändern.

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

Beispielnutzung:

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

Sie werden aufgefordert, das Commit auszuwählen, das Sie ändern möchten, und dann das neue Datum einzugeben.

Wenn Sie ein Commit durch einen bestimmten Hash ändern möchten, führen Sie dies aus git-change-date --hash=[hash]


Ich wollte nur sagen, dass dies großartig ist und wunderbar funktioniert hat. Danke, du hast mir viel Zeit gespart!
Paranza

17

Die folgende Bash-Funktion ändert die Zeit eines Commits für den aktuellen Zweig.

Achten Sie darauf, dass Sie es nicht verwenden, wenn Sie das Commit bereits gepusht haben oder wenn Sie das Commit in einem anderen Zweig verwenden.

# 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
Sie haben einen Fehler darin: if [[ -z "$commit" ]]->if [[ -z "$date_timestamp" ]]
blueFast

Nett! Ich würde empfehlen, die Einstellung GIT_COMMITTER_DATE=am Ende der Methode vorzunehmen, um weitere manuelle Festschreibungen zur Einhaltung des angegebenen Datums zu verhindern.
Loopkin

@loopkin, GIT_COMMITTER_DATE ist nur für den Befehl "git commit" festgelegt, sodass Sie ihn danach nicht mehr löschen müssen
nimrodm

@nimrodm, ich habe gerade nochmal getestet und du bist richtig. Vielen Dank für den Hinweis.
Loopkin

12

So ändern Sie sowohl das Autorendatum als auch das Festschreibungsdatum:

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

10

Wenn Sie das genaue Datum eines anderen Commits erhalten möchten (sagen Sie, Sie haben ein Commit erneut bearbeitet und möchten, dass es das Datum der ursprünglichen Pre-Rebase-Version enthält):

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

Dadurch wird das Datum des HEAD-Commits so korrigiert, dass es genau das Datum des Commits a383243 ist (bei Unklarheiten mehr Ziffern einfügen). Es wird auch ein Editorfenster geöffnet, in dem Sie die Festschreibungsnachricht bearbeiten können.

Dies ist das Autorendatum, für das Sie sich normalerweise interessieren - siehe andere Antworten für das Datum des Committers.


7

Wenn Sie die akzeptierte Antwort ( https://stackoverflow.com/a/454750/72809 ) in der Standard-Windows-Befehlszeile ausführen möchten , benötigen Sie den folgenden Befehl:

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"

Anmerkungen:

  • Es ist möglicherweise möglich, den Befehl auf mehrere Zeilen aufzuteilen (Windows unterstützt die Zeilenaufteilung mit dem Carret-Symbol ^), aber es ist mir nicht gelungen.
  • Sie können ISO-Daten schreiben, was viel Zeit spart, um den richtigen Wochentag zu finden, und allgemeine Frustration über die Reihenfolge der Elemente.
  • Wenn Sie möchten, dass das Datum von Autor und Committer identisch ist, können Sie einfach auf die zuvor festgelegte Variable verweisen.

Vielen Dank an einen Blogbeitrag von Colin Svingen . Obwohl sein Code bei mir nicht funktionierte, half er mir, die richtige Lösung zu finden.


7

Wenn Commit noch nicht gepusht ist, kann ich so etwas verwenden:

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

Danach öffnet git bash den Editor mit dem bereits angewendeten Datum. Sie müssen ihn nur speichern, indem Sie im Befehlsmodus des VI-Editors ": wq" eingeben, und Sie können ihn verschieben


2
Fügen Sie einfach die nette Antwort hinzu: Wenn Sie die Festschreibungsnachricht nicht bearbeiten möchten (wenn Sie nur das Festschreibungsdatum ändern möchten), verwenden Sie die --no-editOption.
Antonio Vinicius Menezes Medei

Wenn das Commit bereits gepusht wurde, können Sie das geänderte Commit weiterhin mit git push -f(erzwungenes Update) pushen . Das kann jedoch Nebenwirkungen haben. (besonders wenn viele Leute lokale Klone des Repository haben)
Antonio Vinicius Menezes Medei


2

Es gibt bereits viele gute Antworten, aber wenn ich das Datum für mehrere Commits an einem Tag oder in einem Monat ändern möchte, finde ich keine richtige Antwort. Also erstelle ich ein neues Skript dafür mit Erläuterung, hoffe es wird jemandem helfen:

#!/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

Das Datum wird geändert:

AuthorDate: Wed Sep 13 13:39:41 2017 +0800
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.