web-dev-qa-db-ja.com

以前に追加したgitサブツリーとその履歴を削除する方法

何ヶ月も前に、gitリポジトリにサブツリーを追加しました。このサブツリーには、いくつかのフォルダーとファイルが含まれていました。サブモジュールを作成する代わりに、サブツリーを追加しました(推奨)。今、私はサブツリー内のファイルの1つだけが必要で、残りは必要ないことに気づきました。さらに悪いことに、私のリポジトリが他のcloneの場合、期待どおりのものではなく、サブツリーや私が作成した他のコードとの競合があります。

私はファイル/フォルダに乗ることができます

git rm subtree–folder1 subtree_folder2 subtree_files.*

ただし、まだサブツリーからの長いコミット履歴が残っています。

最初にサブツリーを追加して以来、かなりの量の開発を行ってきましたが、生成したコミット履歴を失うことはありません。

要するに、これは私が望んでいることです:

  1. すべてのサブツリーファイル/フォルダーを削除します。
  2. すべてのサブツリーコミットの履歴を忘れます。
  3. 私のコードと私の履歴のみを残しました。

これは可能ですか?

PS。考えられる複雑さの1つは、保持したい単一のヘッダーファイルをコードのサブツリーからフォルダーに移動したことです。これが私がサブツリーの履歴を忘れないようにしているものではないことを願っています。

試み

リモートサーバーからの新しいチェックアウト後、私は次のようになりました。

$ ls
.git             CMakeLists.txt   Read.cpp         logging.conf
.gitignore       ENDF6            TestData         src
.sparse-checkout LICENCE          doc              test
.travis.yml      README.md        include          tools

どこ .gitignoreに含まれるもの:build/debug /

提案されているようにコマンドを実行すると、非常に満足のいく応答が得られません。

$ git filter-branch --index-filter 'git rm --cached -rf test tools src doc LICENCE README.md .travis.yml' HEAD
Rewrite 2fec85e41e40ae18efd1b130f55b14166a422c7f (1/1701)fatal: pathspec 'test' did not match any files
index filter failed: git rm --cached -rf test tools src doc LICENCE README.md .travis.yml

testに問題があると明確に示されているのになぜそれが表示されるのかはわかりません。私は困惑しています。

16
jlconlin

フィルターブランチを--Prune-emptyオプションとともに使用して、新しい変更が導入されなくなったコミットを削除する必要があります。

git filter-branch --index-filter 'git rm --cached --ignore-unmatch -rf dir1 dir2 dirN file1 file2 fileN' --Prune-empty -f HEAD

その後、ディスク領域を回復する場合は、フィルターブランチが保存した元の参照をすべて削除し、参照ログを期限切れにして、ガベージコレクションを実行する必要があります。

20
Andrew C

git filter-branchを使用して、ブランチで行ったすべてのコミットに操作を適用できます。これには、履歴全体を書き換えるときに各コミットからファイルを削除することが含まれます。詳しい説明と手順はこちらから入手できます: http://gitready.com/beginner/2009/03/06/ignoring-doesnt-remove-a-file.html 。次の質問も役に立ちます: Gitリポジトリからファイルを完全に削除し、GitHubのリモート (リンクを見つけた場所です)。このソリューションで実行する実際のコマンドは、git filter-branch --index-filter 'git rm --cached -rf subtree–folder1 subtree_folder2' HEADのようになります。

別の方法は、おそらくあなたがやっていることに対してやり過ぎですが、チェリーピッキングです。チェリーピッキングを使用すると、履歴の任意の部分を任意の詳細レベルで書き直すことができます:http://git-scm.com/docs/git-cherry-pick。あなたはgit reset --hard <HASH of commit that introduced the subtree>のようなことをしたいでしょう、その後一連の

git cherry-pick -n <following commit hashes>
git reset
git add -p
git commit

その後のコミットごとに。これにより、過去に行った各コミットからサブツリーを削除できます。効果的なチェリーピッキングの詳細については、 gitを使用した部分的なチェリーピッキング を参照してください。このバージョンの削除が完了したら、ブランチの一部ではなくなった古いコミットを削除する必要があります。

git reflog expire --expire-unreachable=now --all
git gc --Prune=now

その他の参照されている質問: gitでブランチを後方に移動する方法?ブランチの下にないGitコミットのリストおよび削除(ダングリング?)

2
Mad Physicist