Die Ratschläge, die Sie erhalten haben, sind fehlerhaft. Das unbedingte Setzen von GIT_AUTHOR_DATE in einer --env-filter
würde das Datum jeder Übertragung neu schreiben. Außerdem wäre es ungewöhnlich, wenn man Git Commit innerhalb --index-filter
.
Sie haben es hier mit mehreren, voneinander unabhängigen Problemen zu tun.
Angabe von anderen Daten als "jetzt"
Jede Übertragung hat zwei Daten: das Datum des Autors und das Datum des Übertragenden. Sie können jedes Datum überschreiben, indem Sie die Umgebungsvariablen GIT_AUTHOR_DATE und GIT_COMMITTER_DATE für jeden Befehl, der eine neue Übertragung schreibt, mit Werten versehen. Siehe "Datumsformate" in git-commit(1) oder die unten stehenden:
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 bei normalem Gebrauch eine neue Übertragung schreibt, ist Git Commit . Es hat auch eine --date
mit der Sie das Autorendatum direkt angeben können. Ihre voraussichtliche Verwendung umfasst git filter-branch --env-filter
verwendet auch die oben erwähnten Umgebungsvariablen (diese sind Teil der "env", nach der die Option benannt ist; siehe "Optionen" in git-filter-branch(1) und der zugrundeliegende "Klempner"-Befehl git-commit-tree(1) .
Einfügen einer Datei in eine einzelne ref Geschichte
Wenn Ihr Repository sehr einfach ist (d.h. Sie haben nur einen einzigen Zweig, keine Tags), dann können Sie wahrscheinlich Git-Rebase um die Arbeit zu erledigen.
Verwenden Sie in den folgenden Befehlen den Objektnamen (SHA-1-Hash) der Übertragung anstelle von "A". Vergessen Sie nicht, eine der "date override"-Methoden zu verwenden, wenn Sie Git Commit .
---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 wollten, um die neue Datei einzuschließen (anstatt eine neue Übergabe zu erstellen, wo sie hinzugefügt wurde), dann verwenden Sie git commit --amend
anstelle von git commit
. Das Ergebnis würde wie folgt aussehen:
---A'---B'---C'---o---o---o master
Dies funktioniert, solange Sie den Namen des Commits angeben können, der der Elternteil Ihres neuen Commits sein soll. Wenn Sie möchten, dass Ihre neue Datei über einen neuen Root-Commit (ohne Eltern) hinzugefügt wird, dann brauchen 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, das Gleiche zu tun die mit älteren Versionen von Git funktionieren.
Einfügen einer Datei in ein Multi- ref Geschichte
Wenn Ihr Repository komplexer ist (d.h. mehr als eine Referenz hat (Zweige, Tags usw.)), dann müssen Sie wahrscheinlich git filter-branch . Vor der Verwendung git filter-branch sollten Sie eine Sicherungskopie Ihres gesamten Repositorys erstellen. Eine einfache tar Archiv Ihres gesamten Arbeitsbaums (einschließlich des .git-Verzeichnisses) ist ausreichend. git filter-branch erstellt zwar Sicherungskopien, aber es ist oft einfacher, eine nicht ganz korrekte Filterung wiederherzustellen, indem Sie einfach Ihre .git
und die Wiederherstellung aus Ihrer Sicherung.
Hinweis: Die folgenden Beispiele verwenden den untergeordneten Befehl git update-index --add
anstelle von git add
. Sie können verwenden Git hinzufügen aber Sie müssen die Datei zunächst von einem externen Speicherort in den erwarteten Pfad kopieren ( --index-filter
führt seinen Befehl in einem temporären GIT_WORK_TREE aus, der leer ist).
Wenn Sie möchten, dass Ihre neue Datei zu jeder bestehenden Übertragung hinzugefügt wird, können Sie dies 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 nicht wirklich einen Grund, die Daten der vorhandenen Übertragungen mit --env-filter 'GIT_AUTHOR_DATE=…'
. Wenn Sie es verwenden würden, müssten Sie es an Bedingungen knüpfen, damit das Datum bei jeder Übertragung neu geschrieben wird.
Wenn Sie möchten, dass Ihre neue Datei nur in den Commits nach einem bestehenden Commit ("A") auftaucht, dann können Sie dies 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 eine neue Übergabe hinzugefügt wird, die in der Mitte der Historie eingefügt wird, müssen Sie die neue Übergabe vor der Verwendung von git filter-branch und hinzufügen --parent-filter
a git filter-branch :
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 dafür sorgen, dass die Datei zuerst in einem neuen Root-Commit hinzugefügt wird: Erstellen Sie Ihren neuen Root-Commit mit der Methode "orphan" aus der Git-Rebase Abschnitt (erfassen Sie ihn in new_commit
), verwenden Sie die unbedingte --index-filter
und eine --parent-filter
wie "sed -e \"s/^$/-p $new_commit/\""
.