gitリポジトリの履歴を折りたたむ


85

かなり大きな歴史を持つgitプロジェクトがあります。

具体的には、プロジェクトの初期には、プロジェクトにかなりの数のバイナリリソースファイルがありましたが、これらは事実上外部リソースであるため、現在は削除されています。

ただし、これらのファイルが以前にコミットされているため、リポジトリのサイズは> 200MB(現在の合計チェックアウトは約20MB)です。

私たちがやりたいのは、履歴を「折りたたむ」ことです。これにより、リポジトリは以前よりも新しいリビジョンから作成されたように見えます。例えば

1-----2-----3-----4-----+---+---+
                   \       /
                    +-----+---+---+
  1. リポジトリが作成されました
  2. バイナリファイルの大規模なセットが追加されました
  3. バイナリファイルの大規模なセットが削除されました
  4. リポジトリの新しい意図された「開始」

したがって、事実上、特定の時点より前にプロジェクト履歴を失いたいと考えています。この時点ではブランチは1つしかないため、複数の開始点などを処理しようとしても問題はありません。ただし、すべての履歴を失い、現在のバージョンで新しいリポジトリを開始する必要はありません。

これは可能ですか、それとも肥大化したリポジトリを永遠に持つ運命にありますか?

回答:


89

バイナリの膨張を取り除き、残りの履歴を保持することができます。Gitを使用すると、以前のコミットを並べ替えて「押しつぶす」ことができるため、大きなバイナリファイルを追加および削除するコミットのみを組み合わせることができます。追加がすべて1つのコミットで行われ、削除が別のコミットで行われた場合、これは各ファイルを処理するよりもはるかに簡単です。

$ git log --stat       # list all commits and commit messages 

これを検索して、バイナリファイルを追加および削除するコミットを検索し、それらのSHA1、say2bcdefおよび3cdef3

次に、リポジトリの履歴を編集するにはrebase -i、バイナリを追加したコミットの親から始めて、インタラクティブオプションを指定してコマンドを使用します。$ EDITORが起動し、2bcdef次で始まるコミットのリストが表示されます。

$ git rebase -i 2bcdef^    # generate a pick list of all commits starting with 2bcdef
# Rebasing zzzzzz onto yyyyyyy 
# 
# Commands: 
#  pick = use commit 
#  edit = use commit, but stop for amending 
#  squash = use commit, but meld into previous commit 
# 
# If you remove a line here THAT COMMIT WILL BE LOST.
#
pick 2bcdef   Add binary files and other edits
pick xxxxxx   Another change
  .
  .
pick 3cdef3   Remove binary files; link to them as external resources
  .
  .

squash 3cdef32行目として挿入 pick 3cdef3し、リストからその行を削除します。rebaseこれで、バイナリを追加および削除するコミットを1つのコミットに結合する、インタラクティブのアクションのリストができました。その差分は、それらのコミットの他の変更にすぎません。次に、完了するように指示すると、後続のすべてのコミットが順番に再適用されます。

$ git rebase --continue

これには1、2分かかります。
これで、バイナリが出入りすることのないレポができました。ただし、デフォルトでは、Gitはガベージコレクションが可能になるまで30日間変更を保持するため、スペースを占有します。これにより、気が変わる可能性があります。今すぐ削除したい場合:

$ git reflog expire --expire=1.minute refs/heads/master
      #all deletions up to 1 minute  ago available to be garbage-collected
$ git fsck --unreachable      # lists all the blobs(files) that will be garbage-collected
$ git prune
$ git gc                      

これで、膨張を取り除きましたが、残りの履歴は保持しました。


7
他の人がすでにそのリポジトリからプルしている場合は、履歴を書き換えるとプルが混乱することを覚えておく必要があります。git-rebaseマニュアルでは、これらの他のリポジトリを回復する方法について説明しています。 kernel.org/pub/software/scm/git/docs/git-rebase.html
オットー

これは、ユーザー固有の問題に対する優れた回答ですが、実際の質問に対する回答ではありません。davitenioの答えは、実際の質問に対する優れた答えです。
サムワトキンス

27

git filter-branchグラフトとともに使用して、コミット番号4をブランチの新しいルートコミットにすることができます。.git/info/graftsコミット番号4のSHA1を含む1行だけのファイルを作成するだけです。

ここでaを実行すると、git logまたはgitkこれらのコマンドでブランチのルートとしてコミット番号4が表示されることがわかります。しかし、リポジトリでは実際には何も変更されていません。削除.git/info/graftsして、git logまたはの出力をgitk以前と同じにすることができます。実際にコミット番号4を新しいルートにするgit filter-branchには、引数なしで実行する必要があります。


これは、マージコミットの保持に問題がなく、タイムスタンプが変更されないため、リベースよりもはるかに優れています。すべてのリベース方法よりも簡単で高速です。
mmrobins 2011年

実際、そのブランチの一部ではなくなったすべてのコミットを物理的に削除する方法はありますか?git gc --prune=0それらをクリーンアップしていないようです。
verhogen 2012年

1
@verhogengit gc --prune=nowは、参照されなくなったすべてのコミットを物理的にクリーンアップします。これがうまくいかない場合は、古いルートを参照しているリモート追跡ブランチがある可能性があります。でリストしgit branch -r、たとえばでリモートブランチを削除してgit branch -rd origin/masterから、git gc --prune=now再度実行します。
kayahr 2012

20

JesperEの投稿のおかげで、私は調べましたgit-filter-branch-それは実際にあなたが望むものかもしれません。ビッグファイルが削除されてから変更されることを除いて、以前のコミットも保持できるようです。以下からのgit -フィルター分岐のmanページ

すべてのコミットからファイル(機密情報または著作権違反を含む)を削除するとします。

git filter-branch --tree-filter'rm filename 'HEAD

必ずそのマニュアルページを読んでください...明らかに、リポジトリのスペアクローンでこれを実行して、期待どおりに機能することを確認する必要があります。


2
githubのリンクをチェックしてください... git-filter-branchコマンドでいくつかの強力なオプションがあります:help.github.com/articles/remove-sensitive-data
ricosrealm

5

git-fast-exportあなたが探しているものは何ですか?

NAME
   git-fast-export - Git data exporter

SYNOPSIS
   git-fast-export [options] | git-fast-import

DESCRIPTION
   This program dumps the given revisions in a form suitable to be piped into git-fast-
   import(1).

   You can use it as a human readable bundle replacement (see git-bundle(1)), or as a kind
   of an interactive git-filter-branch(1).
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.