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:
Git internal format = <unix timestamp> <time zone offset>, e.g. 1112926393 +0200
RFC 2822 = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601 = e.g. 2005-04-07T22:13:13
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 umfasst git 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 .
---A---B---C---o---o---o master
git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit
---A---N (was ",new-commit", but we delete the tag)
\
B'---C'---o---o---o master
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 von git commit
. Das Ergebnis würde folgendermaßen aussehen:
---A'---B'---C'---o---o---o master
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:
B---C---o---o---o master
git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root
N (was new-root, but we deleted it)
\
B'---C'---o---o---o master
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 verwendet git 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:
new_file=$(git hash-object -w path/to/file)
git filter-branch \
--index-filter \
'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
--tag-name-filter cat \
-- --all
git reset --hard
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:
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
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 :
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -
git filter-branch \
--parent-filter "sed -e s/$before_commit/$new_commit/g" \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
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/\""
.