web-dev-qa-db-ja.com

すべてのコミットでGitリポジトリ内のディレクトリを移動するにはどうすればよいですか?

このディレクトリ構造を含むリポジトリがあるとしましょう:

repo/
  blog/
    _posts/
      some-post.html
  another-file.txt

_postsをリポジトリの最上位に移動したいので、構造は次のようになります。

repo/
  _posts/
    some-post.html
  another-file.txt

これはgit mvで十分簡単ですが、履歴を_postsalwaysがレポのルートに存在するように見せたいし、取得できるようにしたいです。 some-post.html経由のgit log -- _posts/some-post.htmlの全履歴。 git filter-branchでいくつかの魔法を使ってこれを達成できると思いますが、その方法を正確に理解していません。何か案は?

67
mipadi

これを実現するには、サブディレクトリフィルターを使用できます。

 $ git filter-branch --subdirectory-filter blog/ -- --all

編集1:_postsを効果的にルートにしたくない場合は、代わりにツリーフィルターを使用します。

 $ git filter-branch --tree-filter 'mv blog/_posts .' HEAD

編集2:一部のコミットにblog/_postsが存在しなかった場合、上記は失敗します。代わりにこれを使用してください:

 $ git filter-branch --tree-filter 'test -d blog/_posts && mv blog/_posts . || echo "Nothing to do"' HEAD
94
artagnon

Ramkumarの回答は非常に有用で価値がありますが、多くの状況では機能しません。たとえば、ディレクトリを他のサブディレクトリとともに新しい場所に移動する場合。

このため、manページには完璧なコマンドが含まれています。

git filter-branch --index-filter \
  'git ls-files -s | sed "s-\t\"*-&NEWSUBDIR/-" |
   GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
   git update-index --index-info &&
   mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

NEWSUBDIRを目的の新しいディレクトリに置き換えるだけです。 dir1/dir2/dir3 /-などのネストされたディレクトリを使用することもできます

33
theduke