リポジトリ全体を最初のコミットまでどのように縮小しますか?
私は最初のコミットにリベースすることができます、しかしそれは私に2コミットを残すでしょう。最初のコミットの前にコミットを参照する方法はありますか?
おそらく最も簡単な方法は、作業コピーの現在の状態で新しいリポジトリを作成することです。すべてのコミットメッセージを保持したい場合は、まずgit log > original.log
を実行してから、新しいリポジトリの最初のコミットメッセージ用にそれを編集します。
rm -rf .git
git init
git add .
git commit
または
git log > original.log
# edit original.log as desired
rm -rf .git
git init
git add .
git commit -F original.log
最近のバージョンのgitでは、git rebase --root -i
を使うことができます。
最初のコミット以外のコミットごとに、pick
をsquash
に変更します。
私はエイリアスgit squash-all
を作りました。
使用例:git squash-all "a brand new start"
。
[alias]
squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f"
警告:コメントを忘れずに入力してください。そうしないと、デフォルトのコミットメッセージ "A new start"が使用されます。
あるいは、次のコマンドでエイリアスを作成することができます。
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'
git reset $(git commit-tree HEAD^{tree} -m "A new start")
注:ここでの "A new start
"は一例です。自分の言語を使用してください。
スカッシュする必要はありません。git commit-tree
を使用して孤立コミットを作成し、それを実行します。
git commit-tree
を介して単一のコミットを作成する
git commit-tree HEAD^{tree} -m "A new start"
がすることは、
提供されたツリーオブジェクトに基づいて新しいコミットオブジェクトを作成し、新しいコミットオブジェクトIDを標準出力に発行します。 -mまたは-Fオプションが指定されていない限り、ログメッセージは標準入力から読み取られます。
式HEAD^{tree}
は、HEAD
に対応するツリーオブジェクト、つまり現在のブランチの先端を意味します。 Tree-Objects および Commit-Objects を参照してください。
現在のブランチを新しいコミットにリセットする
それからgit reset
は単に現在のブランチを新しく作成されたコミットオブジェクトにリセットします。
このようにして、ワークスペースの何も手を加えられたり、リベース/スカッシュの必要がなくなり、本当に速くなります。そして必要な時間は、リポジトリのサイズや履歴の深さとは無関係です。
これはtemplate/archetype/seed/skeletonとして他のリポジトリを使って新しいプロジェクトで "初期コミット"を作成するのに役立ちます。例えば:
cd my-new-project
git init
git fetch --depth=1 -n https://github.com/toolbear/panda.git
git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit")
これにより、テンプレートレポジトリをリモート(Origin
など)として追加することを避け、テンプレートレポジトリの履歴を最初のコミットにまとめます。
あなたがしたいのがあなたのコミットの全てをルートコミットまで押しつぶすことであるならば、
git rebase --interactive --root
なぜなら、リベース操作は対話式リベースエディタのコミットリストを生成するのに非常にゆっくりと実行され、リベース自体も実行されるからです。
大量のコミットを回避している場合の、2つのより速くより効率的な解決策は次のとおりです。
現在のブランチの先端(つまり最新のコミット)に新しいOrphanブランチを作成するだけです。このOrphanブランチは、まったく新しい個別のコミット履歴ツリーの初期ルートコミットを形成します。これは、すべてのコミットを潰すのと実質的に同じです。
git checkout --Orphan new-master master
git commit -m "Enter commit message for your new initial commit"
# Overwrite the old master branch reference with the new one
git branch -M new-master master
ドキュメンテーション:
もう1つの効率的な解決策は、単純にルートコミット<root>
への混合リセットまたはソフトリセットを使用することです。
git branch beforeReset
git reset --soft <root>
git commit --amend
# Verify that the new amended root is no different
# from the previous branch state
git diff beforeReset
ドキュメンテーション:
echo "message" | git commit-tree HEAD^{tree}
これはHEADのツリーで孤立したコミットを作成し、その名前(SHA-1)を標準出力に出力します。それからブランチをリセットしてください。
git reset SHA-1
これが他の人のために機能するのを念のために、私がこれをやってしまった方法は次のとおりです。
このようなことをすることには常にリスクがあることを忘れないでください。開始する前にsaveブランチを作成することは決して悪い考えではありません。
ログ記録から始める
git log --oneline
最初のコミットまでスクロールし、SHAをコピーする
git reset --soft <#sha#>
ログからコピーしたSHAを付けて<#sha#>
を置き換えます
git status
すべてが緑色であることを確認し、そうでなければgit add -A
を実行してください。
git commit --amend
現在のすべての変更を現在の最初のコミットに修正する
今すぐこのブランチをプッシュすると、そこにあるものが上書きされます。
最も簡単な方法は、現在のブランチを削除するために 'plumbing'コマンドupdate-ref
を使うことです。
現在のブランチを削除するのを防ぐ安全弁があるので、git branch -D
を使用することはできません。
これにより、あなたは新たな初期コミットから始めることができる「初期コミット」状態に戻ります。
git update-ref -d refs/heads/master
git commit -m "New initial commit"
私は移植片を使うことについて何かを読んだが、それをあまり調べなかった。
とにかく、あなたはこれらの最後の2つのコミットを次のようなもので手動で潰すことができます:
git reset HEAD~1
git add -A
git commit --amend
まず、git rebase --interactive
を使用して、すべてのコミットを単一のコミットにまとめます。今、あなたはスカッシュするために2つのコミットを残しました。そうするために、のいずれかを読んでください
git checkout --Orphan new_root_branch && git commit
ファイル.git/info/grafts
を追加し、そこにあなたのルートになりたいコミットハッシュを置きます。
git log
はそのコミットから始まります
それを '本当の'ものにするためにはgit filter-branch
を実行してください。
バックアップを作成する
git branch backup
指定したコミットにリセット
git reset --soft <#root>
その後、すべてのファイルをステージングに追加します
git add .
メッセージを更新せずにコミットする
git commit --amend --no-edit
圧縮されたコミットで新しいブランチにリポジトリをプッシュする
git Push -f
この答えは上記の2つの方法で改善されています(投票してください)。1つのコミットを作成する(親なし、履歴なし)のに加え、あなたはもすべてのコミットデータを保持したいと思いますそのコミットの
もちろん、new/singleコミットのcommit-SHAは変わります。なぜなら、それは新しい(非)履歴を表し、親のない/ root-commitになるからです。
これはgit log
を読み、git commit-tree
のためにいくつかの変数を設定することによって行うことができます。上記のcommit-dataを保持したまま、新しいブランチone-commit
にmaster
から単一のコミットを作成したいと仮定します。
git checkout -b one-commit master ## create new branch to reset
git reset --hard \
$(eval "$(git log master -n1 --format='\
COMMIT_MESSAGE="%B" \
GIT_AUTHOR_NAME="%an" \
GIT_AUTHOR_EMAIL="%ae" \
GIT_AUTHOR_DATE="%ad" \
GIT_COMMITTER_NAME="%cn" \
GIT_COMMITTER_EMAIL="%ce" \
GIT_COMMITTER_DATE="%cd"')" 'git commit-tree master^{tree} <<COMMITMESSAGE
$COMMIT_MESSAGE
COMMITMESSAGE
')
私は通常このようにします:
すべてがコミットされていることを確認し、問題が発生した場合に備えて最新のコミットIDを書き留めるか、バックアップとして別のブランチを作成します。
git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD`
を実行して頭を最初のコミットにリセットしますが、インデックスは変更しません。最初のコミット以降のすべての変更はコミットする準備ができているように見えます。
コミットを最初のコミットに修正してコミットメッセージを変更する場合はgit commit --amend -m "initial commit"
を実行します。既存のコミットメッセージをそのまま使用する場合はgit commit --amend --no-edit
を実行します。
git Push -f
を実行して変更をプッシュする