あなたが与えられたアドバイスには欠陥があります。無条件にGIT_AUTHOR_DATEを設定する--env-filter
と、すべてのコミットの日付が書き換えられます。また、内部でgit commitを使用することはまれ--index-filter
です。
ここでは、複数の独立した問題を扱っています。
「現在」以外の日付の指定
各コミットには、作成者の日付とコミッターの日付の2つの日付があります。新しいコミットを書き込むコマンドの環境変数GIT_AUTHOR_DATEおよびGIT_COMMITTER_DATEを介して値を指定することにより、それぞれをオーバーライドできます。git-commit(1)または以下の「日付形式」を参照してください。
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
通常の使用中に新しいコミットを書き込む唯一のコマンドはgit commitです。また--date
、作成者の日付を直接指定できるオプションもあります。予想される使用法にgit filter-branch --env-filter
は、上記の環境変数も含まれます(これらは「env」の一部であり、その後にオプションの名前が付けられます。git-filter-branch(1)の「オプション」と基になる「配管」コマンドgit-commitを参照してください-tree(1)。
単一の参照履歴へのファイルの挿入
リポジトリが非常にシンプルな場合(つまり、ブランチが1つしかなく、タグがない場合)、おそらくgit rebaseを使用して作業を行うことができます。
次のコマンドでは、「A」の代わりにコミットのオブジェクト名(SHA-1ハッシュ)を使用します。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
あなたはAが(代わりにそれを添加したところ、新しいコミットを作成する)新しいファイルを含めるように更新したい場合は、使用git commit --amend
の代わりにgit commit
。結果は次のようになります。
---A'---B'---C'---o---o---o master
上記は、新しいコミットの親となるコミットに名前を付けることができる限り機能します。新しいルートコミット(親なし)を介して新しいファイルを実際に追加する場合は、少し異なるものが必要です。
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
は比較的新しい(Git 1.7.2)ですが、Gitの古いバージョンで動作する同じことを行う他の方法があります。
マルチ参照履歴へのファイルの挿入
リポジトリがより複雑な場合(つまり、複数の参照(ブランチ、タグなど)がある場合)は、おそらくgit filter-branchを使用する必要があります。git filter-branchを使用する前に、リポジトリ全体のバックアップコピーを作成する必要があります。作業ツリー全体(.gitディレクトリを含む)の単純なtarアーカイブで十分です。git filter-branchはバックアップ参照を作成しますが、.git
ディレクトリを削除してバックアップから復元するだけで、完全に適切ではないフィルタリングから回復する方が簡単な場合がよくあります。
注:以下の例では、のgit update-index --add
代わりに下位レベルのコマンドを使用していgit add
ます。git addを使用することもできますが、最初にファイルを外部の場所から予期されるパスにコピーする必要があります(--index-filter
空の一時GIT_WORK_TREEでコマンドを実行します)。
新しいファイルを既存のすべてのコミットに追加する場合は、次のようにします。
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
で既存のコミットの日付を変更する理由は本当にわかりません--env-filter 'GIT_AUTHOR_DATE=…'
。使用した場合は、条件付きにして、コミットごとに日付を書き換えるようにする必要があります。
既存のコミット(「A」)の後のコミットにのみ新しいファイルを表示する場合は、次のようにします。
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
新しい経由で追加されるファイルは、それがあなたの歴史の途中に挿入されるコミットしたい場合は、新しいは、使用前にコミット生成する必要がありますgitのフィルタ分岐をして追加--parent-filter
するgitのフィルタ分岐:
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
「孤児」メソッドを介してコミットして新しいルートを作成します。また、ファイルが最初にコミットする新しいルートに追加するために手配することができGitのリベースのセクション(キャプチャそれでnew_commit
無条件を使用し、) --index-filter
、および--parent-filter
ように"sed -e \"s/^$/-p $new_commit/\""
。