web-dev-qa-db-ja.com

現在のコミットをGitリポジトリの唯一の(初期の)コミットにしますか?

私は現在ローカルのGitリポジトリを持っています。これをGithubリポジトリにプッシュします。

ローカルリポジトリには約10のコミットがあり、Githubリポジトリはこれと同期した複製です。

私がしたいのは、ローカルのGitリポジトリからすべてのバージョン履歴を削除することです。そのため、リポジトリの現在の内容が唯一のコミットとして表示されます(したがって、リポジトリ内の古いバージョンのファイルは保存されません)。

それから私はこれらの変更をGithubにプッシュしたいと思います。

Git rebaseを調べましたが、特定のバージョンを削除するのにより適しているようです。もう一つの可能​​性のある解決策はローカルレポジトリを削除し、新しいレポジトリを作成することです - これはおそらく多くの作業を生み出すでしょうが!

ETA:追跡されていないディレクトリ/ファイルがあります - 可能であれば、これらのファイルの追跡を維持したいのですが。

592
kaese

これがブルートフォースアプローチです。リポジトリの設定も削除されます。

Note:リポジトリにサブモジュールがある場合、これは機能しません。もしあなたがサブモジュールを使っているなら、あなたは使うべきです。 インタラクティブリベース

手順1:すべての履歴を削除する(バックアップがあることを確認してください。元に戻すことはできません

cat .git/config  # note <github-uri>
rm -rf .git

ステップ2:現在のコンテンツだけでGitリポジトリを再構築する

git init
git add .
git commit -m "Initial commit"

ステップ3:GitHubにプッシュします。

git remote add Origin <github-uri>
git Push -u --force Origin master
913
Fred Foo

私にとって有効な(そしてサブモジュールを機能させ続ける)唯一の解決策は

git checkout --Orphan newBranch
git add -A  # Add all files and commit them
git commit
git branch -D master  # Deletes the master branch
git branch -m master  # Rename the current branch to master
git Push -f Origin master  # Force Push master branch to github
git gc --aggressive --Prune=all     # remove the old files

私がサブモジュールを持っているとき、.git/を削除することは常に大きな問題を引き起こします。 git rebase --rootを使うとどういうわけか私に衝突が起こります(そして私はたくさんの歴史を持っているので時間がかかります)。

528
Zeelot

これは私が支持しているアプローチです。

git branch new_branch_name $(echo "commit message" | git commit-tree HEAD^{tree})

これにより、HEADのすべてを追加する1つのコミットで新しいブランチが作成されます。他に何も変更しないので、完全に安全です。

82
dan_waterworth

もう1つの選択肢は、コミットが多い場合には大変な作業になることがありますが、対話的なリベースです(gitのバージョンが1.7.12以上であると仮定した場合)。git rebase --root -i

エディタにコミットのリストが表示されたら:

  • 最初のコミットのために "pick"を "reword"に変更
  • 他のコミットごとに "pick"を "fixup"に変更

保存して閉じます。 Gitはリベースを開始します。

最後に、それ以降のすべてのものを組み合わせた新しいルートコミットがあります。

利点は、あなたが自分のリポジトリを削除する必要がないということです、そしてあなたが再考するならば、あなたはいつもフォールバックをするということです。

あなたが本当にあなたの歴史を悪くしたいのなら、masterをこのcommitにリセットし、他のすべてのブランチを削除してください。

31
Carl

larsmans の提案された方法の変形:

未追跡ファイルリストを保存します。

git ls-files --others --exclude-standard > /tmp/my_untracked_files

Gitの設定を保存してください。

mv .git/config /tmp/

その後、larsmansの最初のステップを実行してください。

rm -rf .git
git init
git add .

設定を復元します。

mv /tmp/config .git/

あなたが追跡していないファイルの追跡を解除します。

cat /tmp/my_untracked_files | xargs -0 git rm --cached

次にコミットします。

git commit -m "Initial commit"

そして最後にリポジトリにプッシュします。

git Push -u --force Origin master
17
lalebarde

浅い クローン (git> 1.9)を使うことができます。

git clone --depth depth remote-url

さらに読む: http://blogs.atlassian.com/2014/05/handle-big-repositories-git/

5
Matthias M

git filter-branchは主要手術ツールです。

git filter-branch --parent-filter true -- @^!

--parent-filterは両親を標準入力に書き出し、書き換えられた両親を標準出力に表示します。 unix trueは正常に終了して何も表示しません。そのため、親はいません。 @^!Gitの略です。 「ヘッドコミットはしますが、その親はいません」。それから他のすべての参照を削除して、余​​暇にプッシュします。

4
jthill

以下の方法は正確に再現可能であるため、両側で一貫性がある場合はcloneを再度実行する必要はありません。反対側でもスクリプトを実行するだけです。

git log -n1 --format=%H >.git/info/grafts
git filter-branch -f
rm .git/info/grafts

その後、それをクリーンアップしたい場合は、このスクリプトを試してください:

http://sam.nipl.net/b/git-gc-all-ferocious

私はリポジトリの各ブランチに対して "履歴を削除する"スクリプトを書きました。

http://sam.nipl.net/b/git-kill-history

また見なさい: http://sam.nipl.net/b/confirm

2
Sam Watkins

以下は@Zeelotの答えから改作したスクリプトです。マスターブランチだけでなく、すべてのブランチから履歴を削除する必要があります。

for BR in $(git branch); do   
  git checkout $BR
  git checkout --Orphan ${BR}_temp
  git commit -m "Initial commit"
  git branch -D $BR
  git branch -m $BR
done;
git gc --aggressive --Prune=all

それは私の目的のために働いた(私はサブモジュールを使用していない)。

1
Shafique Jamal

Githubレポジトリを削除して新しいものを作成するだけです。はるかに速く、最も簡単で安全な方法です。結局、単一のコミットを持つマスターブランチだけが必要な場合に、受け入れられたソリューションでこれらのコマンドをすべて実行する必要がありますか。

0
AndroidDev

私がしたいのは、ローカルのGitリポジトリからすべてのバージョン履歴を削除することです。そのため、リポジトリの現在の内容が唯一のコミットとして表示されます(したがって、リポジトリ内の古いバージョンのファイルは保存されません)。

より概念的な答え:

タグ/ブランチ/参照がそれらを指していない場合、gitは自動的に古いコミットをガベージコレクションします。そのため、単にすべてのタグ/ブランチを削除し、任意のブランチに関連付けられた新しい孤立コミットを作成する必要があります。慣例により、ブランチmasterにそのコミットをポイントさせることになります。

古くて到達不可能なコミットは、彼らが低レベルのgitコマンドで調べない限り、二度と見られることはありません。それで十分なのであれば、それをやめて、自動GCが望むときはいつでもその仕事をするようにします。すぐにそれらを取り除きたいのなら、git gcを使うことができます(おそらく--aggressive --Prune=allと一緒に)。ただし、リモートのgitリポジトリでは、シェルが自分のファイルシステムにアクセスできない限り、それを強制する方法はありません。

0
AnoE