Ich konvertiere alles für meinen persönlichen Gebrauch in Git und habe einige alte Versionen einer Datei gefunden, die sich bereits im Repository befinden. Wie kann ich es in der richtigen Reihenfolge entsprechend dem "Änderungsdatum" der Datei in den Verlauf übernehmen, damit ich einen genauen Verlauf der Datei habe?
Mir wurde gesagt, dass so etwas funktionieren würde:
git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all
git
version-control
repository
git-commit
Unbekannt
quelle
quelle
git commit --date="xxx day ago" -m "yyy"
reicht für diesen Zweck aus, wenn sich jemand wundert.Antworten:
Der Rat, den Sie erhalten haben, ist fehlerhaft. Das bedingungslose Setzen von GIT_AUTHOR_DATE in a
--env-filter
würde das Datum jedes Commits neu schreiben. Es wäre auch ungewöhnlich, Git Commit im Inneren zu verwenden--index-filter
.Sie haben es hier mit mehreren unabhängigen Problemen zu tun.
Andere Daten als "jetzt" angeben
Jedes Commit hat zwei Daten: das Autorendatum und das Committerdatum. Sie können jeden überschreiben, indem Sie Werte über die Umgebungsvariablen GIT_AUTHOR_DATE und GIT_COMMITTER_DATE für jeden Befehl angeben, der ein neues Commit schreibt. Siehe "Datumsformate" in git-commit (1) oder unten:
Der einzige Befehl, der während des normalen Gebrauchs ein neues Commit schreibt, ist git commit . Es gibt auch eine
--date
Option, mit der Sie das Autorendatum direkt angeben können. Ihre erwartete Verwendung umfasstgit filter-branch --env-filter
auch die oben genannten Umgebungsvariablen (diese sind Teil der "env", nach der die Option benannt ist; siehe "Optionen" in git-filter-branch (1) und den zugrunde liegenden "plumbing" -Befehl git-commit -Baum (1) .Einfügen einer Datei in eine Einzel ref Geschichte
Wenn Ihr Repository sehr einfach ist (dh Sie haben nur einen einzigen Zweig, keine Tags), können Sie wahrscheinlich die Git-Rebase verwenden , um die Arbeit zu erledigen.
Verwenden Sie in den folgenden Befehlen den Objektnamen (SHA-1-Hash) des Commits anstelle von "A". Vergessen Sie nicht, beim Ausführen von git commit eine der Methoden zum Überschreiben von Datumsangaben zu verwenden .
Wenn Sie A aktualisieren möchten, um die neue Datei einzuschließen (anstatt ein neues Commit zu erstellen, in dem es hinzugefügt wurde), verwenden Sie
git commit --amend
stattdessen anstelle vongit commit
. Das Ergebnis würde folgendermaßen aussehen:Das Obige funktioniert so lange, wie Sie das Commit benennen können, das das übergeordnete Element Ihres neuen Commits sein soll. Wenn Sie tatsächlich möchten, dass Ihre neue Datei über ein neues Root-Commit hinzugefügt wird (keine Eltern), benötigen Sie etwas anderes:
git checkout --orphan
ist relativ neu (Git 1.7.2), aber es gibt andere Möglichkeiten, dasselbe zu tun , die bei älteren Versionen von Git funktionieren.Einfügen eine Datei in einem Multi - ref Geschichte
Wenn Ihr Repository komplexer ist (dh mehr als eine Referenz (Zweige, Tags usw.) hat), müssen Sie wahrscheinlich den Git-Filter-Zweig verwenden . Bevor Sie git filter-branch verwenden , sollten Sie eine Sicherungskopie Ihres gesamten Repositorys erstellen. Ein einfaches Tar- Archiv Ihres gesamten Arbeitsbaums (einschließlich des .git-Verzeichnisses) ist ausreichend. git filter-branch erstellt zwar Sicherungsreferenzen, aber es ist oft einfacher, sich von einer nicht ganz richtigen Filterung zu erholen, indem Sie einfach Ihre löschen
.git
Verzeichnis und es aus Ihrer Sicherung wiederherstellen.Hinweis: In den folgenden Beispielen wird
git update-index --add
anstelle des Befehls der unteren Ebene der Befehl verwendetgit add
. Sie könnten git add verwenden , aber Sie müssten zuerst die Datei von einem externen Speicherort in den erwarteten Pfad kopieren (--index-filter
führt den Befehl in einem temporären GIT_WORK_TREE aus, der leer ist).Wenn Sie möchten, dass Ihre neue Datei zu jedem vorhandenen Commit hinzugefügt wird, können Sie Folgendes tun:
Ich sehe keinen Grund, die Daten der bestehenden Commits mit zu ändern
--env-filter 'GIT_AUTHOR_DATE=…'
. Wenn Sie es verwendet hätten, hätten Sie es an Bedingungen geknüpft, damit das Datum für jedes Commit neu geschrieben wird.Wenn Sie möchten, dass Ihre neue Datei erst nach einem vorhandenen Commit („A“) in den Commits angezeigt wird, können Sie Folgendes tun:
Wenn Sie möchten, dass die Datei über ein neues Commit hinzugefügt wird, das in die Mitte Ihres Verlaufs eingefügt werden soll, müssen Sie das neue Commit generieren, bevor Sie git filter-branch verwenden und
--parent-filter
zu git filter-branch hinzufügen :Sie können auch festlegen, dass die Datei zuerst in einem neuen Root-Commit hinzugefügt wird: Erstellen Sie Ihr neues Root-Commit über die "Orphan" -Methode im Abschnitt " Git-Rebase " (erfassen Sie es
new_commit
), verwenden Sie das Unbedingte--index-filter
und--parent-filter
dergleichen"sed -e \"s/^$/-p $new_commit/\""
.quelle
--index-filter
von zurückgegebenen Commits anzuwendengit rev-list
? Im Moment wird der Indexfilter auf eine Untergruppe von Rev-Listen angewendet. Schätzen Sie jeden Einblick.-- --all
für mehrere Refs werden alle Commits verarbeitet, die von jedem Ref aus erreichbar sind. Das letzte Beispiel zeigt, wie Sie nur bestimmte Commits ändern (testen Sie einfach GIT_COMMIT für alles, was Sie möchten). Um nur eine bestimmte Liste von Commits zu ändern, können Sie die Liste vor dem Filtern speichern (z. B.git rev-list … >/tmp/commits_to_rewrite
) und dann die Mitgliedschaft im Filter testen (zif grep -qF "$GIT_COMMIT" /tmp/commits_to_rewrite; then git update-index …
. B. ). Was genau versuchst du zu erreichen? Vielleicht möchten Sie eine neue Frage beginnen, wenn es zu viel ist, um sie in Kommentaren zu erklären.import-directories.perl
aus Gitcontrib/
(oderimport-tars.perl
oderimport-zips.py
...) ein neues Git-Repository aus Ihren Snapshots erstellen (auch mit) "Alte" Zeitstempel). Dierebase
/filter-branch
Techniken in meiner Antwort werden nur benötigt, wenn Sie eine Datei einfügen möchten, die aus dem Verlauf eines vorhandenen Repositorys „weggelassen“ wurde.Sie können das Commit wie gewohnt erstellen. Wenn Sie jedoch ein Commit durchführen, legen Sie die Umgebungsvariablen
GIT_AUTHOR_DATE
undGIT_COMMITTER_DATE
die entsprechenden Datumszeiten fest.Dadurch wird das Commit natürlich an der Spitze Ihres Zweigs ausgeführt (dh vor dem aktuellen HEAD-Commit). Wenn du es im Repo weiter zurückschieben willst, musst du ein bisschen ausgefallen sein. Angenommen, Sie haben diese Geschichte:
Und Sie möchten, dass Ihr neues Commit (markiert als "X") als zweites angezeigt wird :
Am einfachsten ist es, vom ersten Commit zu verzweigen, das neue Commit hinzuzufügen und dann alle anderen Commits über das neue zu setzen. Wie so:
quelle
GIT_AUTHOR_DATE='Fri Jul 26 19:32:10 2013 -0400' GIT_COMMITTER_DATE='Fri Jul 26 19:32:10 2013 -0400' git commit
2013-07-26T19:32:10
: kernel.org/pub/software/scm/git/docs/…THE_TIME='2019-03-30T8:20:00 -0500' GIT_AUTHOR_DATE=$THE_TIME GIT_COMMITTER_DATE=$THE_TIME git commit -m 'commit message here'
Ich weiß, dass diese Frage ziemlich alt ist, aber genau das hat bei mir funktioniert:
quelle
--date
auch das vom Menschen lesbare relative Datumsformat unterstützt wird.git --date
Ändert nur das $ GIT_AUTHOR_DATE. Abhängig von den Umständen wird das aktuelle Datum angezeigt, das mit dem Commit verbunden ist ($ GIT_COMMITTER_DATE)git show <commit-hash> --format=fuller
. Dort sehen Sie dieAuthorDate
das Datum, das Sie angegeben haben, aberCommitDate
das tatsächliche Datum des Commits.In meinem Fall hatte ich im Laufe der Zeit eine Reihe von Versionen von myfile als myfile_bak, myfile_old, myfile_2010, Backups / myfile usw. gespeichert. Ich wollte den Verlauf von myfile anhand ihrer Änderungsdaten in git einfügen. So benennen Sie die älteste bis Meinedat,
git add myfile
danngit commit --date=(modification date from ls -l) myfile
umbenennen nächsten älteste Meinedat, begeht eine andere git mit --date, wiederholt ...Um dies etwas zu automatisieren, können Sie shell-foo verwenden, um die Änderungszeit der Datei abzurufen. Ich habe mit
ls -l
und angefangencut
, aber stat (1) ist direkterquelle
--date
" Überschreiben Sie das im Commit verwendete Autorendatum."git log
's Date scheint das AuthorDate zu sein,git log --pretty=fuller
zeigt sowohl AuthorDate als auch CommitDate an.git commit
Option--date
ändert nur dieGIT_AUTHOR_DATE
, nicht dieGIT_COMMITTER_DATE
. Wie das Pro Git Book erklärt: "Der Autor ist die Person, die das Werk ursprünglich geschrieben hat, während der Committer die Person ist, die das Werk zuletzt angewendet hat." Im Zusammenhang mit DatumsangabenGIT_AUTHOR_DATE
ist dies das Datum, an dem die Datei geändert wurde, während diesGIT_COMMITTER_DATE
das Datum ist, an dem sie festgeschrieben wurde. Hierbei ist zu beachten, dassgit log
Autorendaten standardmäßig als "Datum" angezeigt werden, dann jedoch Festschreibungsdaten zum Filtern verwendet werden, wenn eine--since
Option angegeben wird.stat -c %y
in macOS (und anderen BSD-Varianten) iststat -f %m
.Im Folgenden ist das, was ich Änderungen zu übernehmen verwenden , um auf
foo
zuN=1
Tagen in der Vergangenheit:Wenn Sie sich auf ein noch älteres Datum festlegen möchten, z. B. vor 3 Tagen, ändern Sie einfach das
date
Argument :date -v-3d
.Das ist sehr nützlich, wenn Sie beispielsweise gestern vergessen haben, etwas zu begehen.
UPDATE : Akzeptiert
--date
auch Ausdrücke wie--date "3 days ago"
oder sogar--date "yesterday"
. Wir können es also auf einen Zeilenbefehl reduzieren:quelle
git --date
Ändert nur $ GIT_AUTHOR_DATE. Abhängig von den Umständen wird das aktuelle Datum für das Commit angezeigt ($ GIT_COMMITTER_DATE)git commit --amend --date="$(stat -c %y fileToCopyMTimeFrom)"
git commit --amend --date="$(date -R -d '2020-06-15 16:31')"
In meinem Fall ist mein Git-Prozess bei Verwendung der Option --date abgestürzt. Vielleicht habe ich etwas Schreckliches getan. Infolgedessen wurde eine index.lock-Datei angezeigt. Also habe ich die .lock-Dateien manuell aus dem .git-Ordner gelöscht und ausgeführt, damit alle geänderten Dateien in verstrichenen Daten festgeschrieben werden, und diesmal hat es funktioniert. Vielen Dank für alle Antworten hier.
quelle
git commit --date
. Außerdem sollte Ihre Beispiel-Commit-Nachricht geändert werden, um schlechte einzeilige Nachrichten wie diese zu unterbinden. @JstRoRRgit --date
Ändert nur $ GIT_AUTHOR_DATE. Abhängig von den Umständen wird das aktuelle Datum für das Commit angezeigt ($ GIT_COMMITTER_DATE)Um ein , das aussieht begehen , wie es in der Vergangenheit getan wurde , um Sie setzen müssen beide
GIT_AUTHOR_DATE
undGIT_COMMITTER_DATE
:wo
date -d'...'
kann genaues Datum wie2019-01-01 12:00:00
oder relativ wie sein5 months ago 24 days ago
.Um beide Daten im Git-Protokoll anzuzeigen, verwenden Sie:
Dies funktioniert auch für Merge-Commits:
quelle
Sie können jederzeit ein Datum auf Ihrem Computer ändern, ein Commit durchführen, dann das Datum zurück ändern und drücken.
quelle
Oder verwenden Sie einfach einen Fake-Git-Verlauf , um ihn für einen bestimmten Datenbereich zu generieren.
quelle