Close

Git prune

git prune コマンドは、到達不能な Git オブジェクトまたは「孤立した」Git オブジェクトをクリーン・アップするハウスキーピング・ユーティリティです。到達不能なオブジェクトとは、どの ref からもアクセスできないオブジェクトです。ブランチやタグを介してアクセスできないコミットは、到達不能と見なされます。git prune は一般的に直接実行されません。prune はガベージ・コレクション・コマンドと見なされ、git gc コマンドの子コマンドです。


Git prune の概要


git prune の効果を理解するには、コミットが到達不能になるシナリオをシミュレートする必要があります。以下に、このエクスペリエンスをシミュレートする一連のコマンドラインの実行を示します。

~ $ cd git-prune-demo/
~/git-prune-demo $ git init .
Initialized empty Git repository in /Users/kev/Dropbox/git-prune-demo/.git/
~/git-prune-demo $ echo "hello git prune" > hello.txt
~/git-prune-demo $ git add hello.txt
~/git-prune-demo $ git commit -am "added hello.txt"

前述のコマンドのシーケンスでは、git-prune-demo という名前のディレクトリに新しいリポジトリが作成されます。新しいファイル hello.text で構成されるコミットが 1 つ、"hello git prune" の基本コンテンツとともにリポジトリに追加されます。次に、modify hello.txt を変更し、その変更から新しいコミットを作成します。

~/git-prune-demo $ echo "this is second line txt" >> hello.txt
~/git-prune-demo $ cat hello.txt
hello git prune
this is second line txt
~/git-prune-demo $ git commit -am "added another line to hello.txt"
[main 5178bec] added another line to hello.txt
1 file changed, 1 insertion(+)
データベース
関連資料

Git リポジトリ全体を移動する方法

Bitbucket ロゴ
ソリューションを見る

Bitbucket Cloud での Git の使用方法についてのチュートリアルです。

これで、このデモ リポジトリには 2 つのコミット履歴があります。これは git log を使用して検証できます。

~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

        added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

git log の出力には、2 つのコミットと、hello.txt に加えられた編集に関して、これらのコミットに対応するコミット・メッセージが表示されます。次のステップは、コミットの 1 つを到達不能にすることです。これを行うには、git reset コマンドを使用します。リポジトリの状態を最初のコミットである「added hello.txt」コミットにリセットします。

~/git-prune-demo $ git reset --hard 994b122045cf4bf0b97139231b4dd52ea2643c7e
HEAD is now at 994b122 added hello.txt

ここで git log を使用してリポジトリの状態を調べると、コミットが 1 つしかないことがわかります。

~/git-prune-demo $ git log
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

デモ リポジトリは、切り離されたコミットを含む状態になりました。"added another line to hello.txt" というメッセージが表示された 2 つ目のコミットは git log 出力には表示されなくなり、切り離されました。コミットが失われたか削除されたかのように見えるかもしれませんが、Git は履歴を削除しないことに関しては非常に厳格です。git checkout を使用して直接アクセスすることで、まだ利用可能であるが切り離されていることを確認できます。

~/git-prune-demo $ git checkout 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Note: checking out '5178becc2ca965e1728554ce1cb8de2f2c2370b1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

      git checkout -b <new-branch-name>

HEAD is now at 5178bec... added another line to hello.txt
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

      added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

      added hello.txt

切り離されたコミットをチェックアウトするとき、Git は親切にも、私たちが切り離された状態にあることを説明する詳細なメッセージを表示してくれます。ここでログを調べると、"added another line to hello.txt" のコミットがログ出力に戻っていることを確認できます! これで、リポジトリが切り離されたコミットとともに良好なシミュレーション状態にあることがわかったので、git prune の使用を実行できます。まず、git checkout を使用して main ブランチに戻りましょう。

~/git-prune-demo $ git checkout main
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

      5178bec added another line to hello.txt

If you want to keep it by creating a new branch, this may be a good time
to do so with:

     git branch <new-branch-name> 5178bec

Switched to branch 'main'

git checkout 経由で main に戻ると、Git はまたもや親切にも、私たちが切り離されたコミットを後に残そうとしていることを示してくれます。今こそ、切り離されたコミットを prune するときです!次に、git prune を実行しますが、いくつかのオプションを必ず渡す必要があります。--dry-run--verbose を使用すると、prune するように設定されているが実際には prune されない内容を示す出力が表示されます。

~/git-prune-demo $ git prune --dry-run --verbose

このコマンドはほとんどの場合、空の出力を返します。空の出力は、prune によって実際には何も削除されないことを意味します。なぜこのようになるのでしょうか?このコミットは完全には切り離されていない可能性が高いです。どこかで Git はまだこれに対する参照を維持しています。これは、git prunegit gc の外部においてスタンドアロンで使用されない代表的な例です。これは、Git でデータを完全に失うことがいかに難しいかを示す良い例でもあります。

ほとんどの場合、Git は切り離されたコミットへの参照を reflog に格納しています。これは、git reflog を実行することで調査できます。ここにたどり着くために実行した一連のアクションを説明する出力が表示されるはずです。git reflog の詳細については、git reflog のページをご覧ください。reflog に履歴を保存することに加えて、Git には、切り離されたコミットを prune 実行するタイミングに関する内部的な有効期限があります。繰り返しますが、これらはすべて git gc が処理する実装の詳細であり、git prune はスタンドアロンで使用すべきではありません。

git prune シミュレーションのデモを締めくくるには、reflog をクリアしなければなりません。

~/git-prune-demo $ git reflog expire --expire=now --expire-unreachable=now --all

上記のコマンドは、現在よりも古い reflog へのすべてのエントリを強制的に期限切れにします。これは容赦のない危険なコマンドなので、一時的なGit ユーザーとしては決して使用する必要がないようにすべきです。このコマンドを実行して、git prune の成功を実証しています。reflog を完全に消去した状態で、git prune を実行できるようになりました。

~/git-prune-demo $ git prune --dry-run --verbose --expire=now
1782293bdfac16b5408420c5cb0c9a22ddbdd985 blob
5178becc2ca965e1728554ce1cb8de2f2c2370b1 commit
a1b3b83440d2aa956ad6482535cbd121510a3280 commit
f91c3433eae245767b9cd5bdb46cd127ed38df26 tree

このコマンドは、上記のような Git SHA オブジェクト参照のリストを出力します。

使用法


git prune には、概要セクションで取り上げたオプションの短いリストがあります。

-n --dry-run

prune は実行しません。単に何を行うかを示す出力が表示されます。

-v --verbose

prune によって実行されたすべてのオブジェクトとアクションの出力を表示します。

--progress

prune の進行状況を示す出力を表示します。

--expire <time>

<time>を過ぎたオブジェクトを強制的に期限切れにします。

<head>…

<head> を指定すると、その head ref のオプションがすべて保持されます。

ディスカッション


git prune、git fetch --prune、git remote prune の違いは何ですか?

git remote prunegit fetch --prune の処理内容は同じです。リモート上に存在しないブランチへの参照を削除します。これは、main へのマージ後にリモート ブランチが削除されるチーム ワークフローで作業する場合に非常に適しています。2 番目のコマンド git fetch --prune はリモートに接続し、prune の前に最新のリモート状態をフェッチします。基本的には以下のコマンドの組み合わせです。

git fetch --all && git remote prune

汎用的な git prune コマンドはまったく異なります。概要セクションで説明したように、git prune は、ローカルで切り離されたコミットを削除します。

古いブランチをクリーン アップするにはどうすればいいですか?

git fetch --prune は、古いブランチをクリーン アップするのに最適なユーティリティです。共有リモート リポジトリに接続し、すべてのリモート ブランチ参照をフェッチします。その後、リモート リポジトリで使用されなくなったリモート参照を削除します。

git remote prune origin はローカル ブランチを削除しますか?

いいえ、git remote prune origin は、もはや存在しないリモート ブランチへの参照のみを削除します。git はローカルとリモートの両方の参照を保存します。リポジトリには、local/originremote/origin の参照コレクションがあります。git remote prune origin は、remote/origin 内の参照のみを prune 実行します。これにより、local/origin 内のローカルの作業が安全に残されます。

git prune の要約


git prune コマンドは git gc の子コマンドとして呼び出されることを意図しています。日々のソフトウェア エンジニアリング能力で git prune を呼び出す必要はほとんどありません。git prune の効果を理解するには、他のコマンドが必要です。この記事で使用したコマンドには、git loggit refloggit checkout などがあります。


この記事を共有する
次のトピック

おすすめコンテンツ

次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。

一面のツールを使ってコラボレーションしている人たち

Bitbucket ブログ

DevOps のイラスト

DevOps ラーニング パス

Demo Den アトラシアン・エキスパートによる機能デモ

Bitbucket Cloud が、Atlassian Open DevOps とどのように連携するか

DevOps ニュースレター購読

Thank you for signing up