250

この特定のシナリオのようなものを見つけることができなかったのではないかと思います。

私は多くの歴史を持つgitリポジトリを持っています:500以上のブランチ、500以上のタグ、2007年半ばにさかのぼります。約19,500のコミットが含まれています。2010年1月1日より前のすべての履歴を削除して、より小さく、扱いやすくしたいと考えています(履歴の完全なコピーをアーカイブリポジトリに保持します)。

新しいリポジトリのルートになりたいというコミットを知っています。ただし、そのコミットで開始するためにリポジトリを切り捨てるための正しいgitmojoを理解することはできません。私はいくつかの変種を推測しています

git filter-branch

移植を含むことが必要になるでしょう。また、保持したい200以上のブランチのそれぞれを個別に処理してから、リポジトリにパッチを適用して戻す必要がある場合もあります(私知っている方法)。

誰かがこのようなことをしたことがありますか?それが重要な場合は、git1.7.2.3を使用しています。

4

12 に答える 12

187

返信を投稿するには遅すぎるかもしれませんが、このページはGoogleの最初の結果であるため、それでも役立つ場合があります。

gitレポジトリのスペースを解放したいが、すべてのコミット(リベースまたはグラフト)を再構築したくないが、完全なレポジトリを持っている人からプッシュ/プル/マージできる場合は、gitを使用できます 浅いクローンのクローン(--depthパラメーター)。

; Clone the original repo into limitedRepo
git clone file:///path_to/originalRepo limitedRepo --depth=10

; Remove the original repo, to free up some space
rm -rf originalRepo
cd limitedRepo
git remote rm origin

次の手順に従うことで、既存のリポジトリを浅くすることができる場合があります。

; Shallow to last 5 commits
git rev-parse HEAD~5 > .git/shallow

; Manually remove all other branches, tags and remotes that refers to old commits

; Prune unreachable objects
git fsck --unreachable ; Will show you the list of what will be deleted
git gc --prune=now     ; Will actually delete your data

すべてのgitローカルタグを削除するにはどうすればよいですか?

追伸:古いバージョンのgitは、浅いリポジトリからのクローン/プッシュ/プルをサポートしていませんでした。

于 2016-01-16T16:51:42.700 に答える
129

新しいルートコミットの親のグラフトを、親なし(または、リポジトリの実際のルートコミットなどの空のコミット)に作成できます。例えばecho "<NEW-ROOT-SHA1>" > .git/info/grafts

グラフトを作成すると、すぐに有効になります。git log不要な古いコミットがなくなったことを確認して確認できるはずです。

$ echo 4a46bc886318679d8b15e05aea40b83ff6c3bd47 > .git/info/grafts
$ git log --decorate | tail --lines=11
commit cb3da2d4d8c3378919844b29e815bfd5fdc0210c
Author: Your Name <your.email@example.com>
Date:   Fri May 24 14:04:10 2013 +0200

    Another message
 
commit 4a46bc886318679d8b15e05aea40b83ff6c3bd47 (grafted)
Author: Your Name <your.email@example.com>
Date:   Thu May 23 22:27:48 2013 +0200

    Some message

すべてが意図したとおりに見える場合は、git filter-branch -- --allそれを永続的にするために利用できます。

注意:フィルターブランチの手順を実行すると、すべてのコミットIDが変更されるため、古いリポジトリを使用しているユーザーは、新しいリポジトリを使用しているユーザーとマージしないでください。

于 2011-02-05T19:46:20.287 に答える
74

この方法は理解しやすく、うまく機能します。スクリプト()への引数$1は、履歴を保持したいコミットの参照(タグ、ハッシュ、...)です。

#!/bin/bash
git checkout --orphan temp $1 # create a new branch without parent history
git commit -m "Truncated history" # create a first commit on this branch
git rebase --onto temp $1 master # now rebase the part of master branch that we want to keep onto this branch
git branch -D temp # delete the temp branch

# The following 2 commands are optional - they keep your git repo in good shape.
git prune --progress # delete all the objects w/o references
git gc --aggressive # aggressively collect garbage; may take a lot of time on large repos

古いタグは引き続き存在することに注意してください。したがって、手動で削除する必要があるかもしれません

備考:これは@yoyodinとほぼ同じですが、ここにはいくつかの重要な追加のコマンドと情報があります。回答を編集しようとしましたが、@ yoyodinの回答が大幅に変更されたため、編集が却下されましたので、こちらの情報をご覧ください。

于 2014-05-21T15:41:47.400 に答える
58

この方法を試してくださいgit履歴を切り捨てる方法:

#!/bin/bash
git checkout --orphan temp $1
git commit -m "Truncated history"
git rebase --onto temp $1 master
git branch -D temp

$1これが保持したいコミットのSHA-1であり、スクリプトはとの間のすべてのコミットを含む新しいブランチを作成$1master、古い履歴はすべて削除されます。この単純なスクリプトは、という名前の既存のブランチがないことを前提としていることに注意してくださいtemp。また、このスクリプトは古い履歴のgitデータをクリアしないことに注意してください。git gc --prune=all && git repack -a -f -F -d本当にすべての履歴を失いたいことを確認した後に実行します。rebase --preserve-mergesまた、その機能のgit実装は完全ではないことに注意する必要があるかもしれません。それを使用する場合は、結果を手動で検査してください。

于 2011-07-25T11:17:32.470 に答える
36

履歴を書き換える代わりに、ProGitブックのこの記事のgit replaceように使用することを検討してください。説明した例では、親コミットを置き換えてツリーの開始をシミュレートすると同時に、完全な履歴を保管用の個別のブランチとして保持します。

于 2012-10-26T19:17:06.383 に答える
29

アップストリームリポジトリを完全な履歴で保持したいが、ローカルの小規模なチェックアウトを保持したい場合は、を使用してシャロークローンを作成します。git clone --depth=1 [repo]

コミットをプッシュした後、あなたはすることができます

  1. git fetch --depth=1古いコミットを整理します。これにより、古いコミットとそのオブジェクトに到達できなくなります。
  2. git reflog expire --expire-unreachable=now --all。すべての古いコミットとそのオブジェクトを期限切れにする
  3. git gc --aggressive --prune=all古いオブジェクトを削除するには

コミット後にローカルのgit履歴を削除する方法も参照してください。。

この「浅い」リポジトリを別の場所にプッシュすることはできないことに注意してください:「浅い更新は許可されていません」。GitリモートURLを変更した後、リモート拒否(浅い更新は許可されません)を参照してください。あなたがそれをしたいのなら、あなたは接ぎ木に固執しなければなりません。

于 2016-05-08T22:21:05.780 に答える
23

私が何をしていたかを理解するために、いくつかの答えと他のいくつかの情報を読む必要がありました。

1.特定のコミットより古いものはすべて無視します

このファイル.git/info/graftsは、コミットの偽の親を定義できます。コミットIDだけの行は、コミットに親がないことを示しています。過去2000回のコミットのみを考慮していると言いたい場合は、次のように入力できます。

git rev-parse HEAD~2000 > .git/info/grafts

git rev-parseは、現在のコミットの2000番目の親のコミットIDを提供します。上記のコマンドは、グラフトファイルが存在する場合は上書きします。それが最初にあるかどうかを確認してください。

2. Git履歴を書き換えます(オプション)

この接ぎ木された偽の親を本物にしたい場合は、次を実行します。

git filter-branch -- --all

すべてのコミットIDが変更されます。このリポジトリのすべてのコピーを強制的に更新する必要があります。

3.ディスクスペースをクリーンアップします

コピーをアップストリームとの互換性を維持したかったので、ステップ2は実行しませんでした。ディスク容量を節約したかっただけです。すべての古いコミットを忘れるために:

git prune
git gc

代替:浅いコピー

別のリポジトリの浅いコピーがあり、ディスクスペースを節約したい場合は、を更新できます.git/shallow。ただし、以前からのコミットを指しているものがないことに注意してください。したがって、次のようなものを実行できます。

git fetch --prune
git rev-parse HEAD~2000 > .git/shallow
git prune
git gc

浅い場所への入場はグラフトのように機能します。ただし、グラフトと浅い部分を同時に使用しないように注意してください。少なくとも、そこに同じエントリがない場合は失敗します。

古いコミットを指す古い参照(タグ、ブランチ、リモートヘッド)がまだある場合、それらはクリーンアップされず、ディスク領域を節約できません。

于 2017-05-01T06:33:56.873 に答える
3

リベースまたはヘッド/マスターにプッシュすると、このエラーが発生する可能性があります

remote: GitLab: You are not allowed to access some of the refs!
To git@giturl:main/xyz.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@giturl:main/xyz.git'

gitダッシュボードでこの問題を解決するには、「保護されたブランチ」からマスターブランチを削除する必要があります

ここに画像の説明を入力してください

次に、このコマンドを実行できます

git push -f origin master

また

git rebase --onto temp $1 master
于 2017-01-03T15:55:54.437 に答える
2

ここには最新ではない答えが多すぎて、結果を完全に説明していないものもあります。最新のgit2.26を使用して履歴を削除するために私が働いたのは次のとおりです。

まず、ダミーのコミットを作成します。このコミットは、切り捨てられたリポジトリの最初のコミットとして表示されます。このコミットは、保持している履歴のすべてのベースファイルを保持するため、これが必要です。SHAは、保持するコミットの前のコミットのIDです(この例では、8365366)。文字列「Initial」は、最初のコミットのコミットメッセージとして表示されます。Windowsを使用している場合は、GitBashコマンドプロンプトから以下のコマンドを入力します。

# 8365366 is id of parent commit after which you want to preserve history
echo 'Initial' | git commit-tree 8365366^{tree}

上記のコマンドは、たとえば、SHAを出力しd10f7503bc1ec9d367da15b540887730db862023ます。

ここで、次のように入力します。

# d10f750 is commit ID from previous command
git rebase --onto d10f750 8365366

これにより、最初にコミット時のすべてのファイル8365366がダミーのコミットに入れられますd10f750。次に、 8365366以降d10f750のすべてのコミットを上から再生します。最後masterに、最後のコミットが再生されるようにブランチポインタが更新されます。

これらの切り捨てられたリポジトリをプッシュする場合は、を実行してくださいgit push -f

覚えておくべきいくつかの事柄(これらはこの方法だけでなく他の方法にも当てはまります):タグは転送されません。コミットIDとタイムスタンプは保持されますが、GitHubはこれらのコミットをのような一括見出しで表示しますCommits on XY date

幸い、切り捨てられた履歴を「アーカイブ」として保持することが可能であり、後で、トリミングされたリポジトリをアーカイブリポジトリに戻すことができます。これを行うには、このガイドを参照してください。

于 2020-05-18T09:59:19.373 に答える
0

以前に複製された既存のリポジトリの場合--depth

git clone --depth=1 ...

ただやる

git pull --depth=1 --update-shallow

https://git-scm.com/docs/git-pull

于 2021-09-15T06:27:50.620 に答える
-3

BFGツールのGitリポジトリによると、「git-filter-branchと同じように、大きなブロブや厄介なブロブを削除しますが、より高速です。Scalaで記述されています」。

https://github.com/rtyley/bfg-repo-cleaner

于 2017-08-07T14:11:38.757 に答える
-10
  1. gitデータ、rm.gitを削除します
  2. git init
  3. gitリモートを追加します
  4. フォースプッシュ
于 2015-01-22T05:26:22.080 に答える