はじめに
アプリ開発において「Git」は必須スキルになっています。Gitには様々なコマンドが存在し、それらを適切に使用することで、開発作業の安全性を高め、効率化を実現できます。
今回は、私が以前参加していた長期にわたる大規模プロジェクトでの経験をお話しします。プロジェクトが進行するにつれ、Gitの操作に時間がかかるようになり、パフォーマンスの低下が見られ始めました。この問題が発生した際、チームメンバーが「git gc」コマンドの実行を提案しました。当時、私はこのコマンドを知りませんでしたが、後にそれがGitリポジトリのメンテナンスに不可欠なものであることを学びました。小規模な個人プロジェクトではあまり必要とされないかもしれませんが、大規模プロジェクトではリポジトリのメンテナンスを行う上で欠かせないコマンドです。
この記事では、リポジトリのメンテナンスに不可欠な「git gc」を解説します。様々なGitコマンドを習得し、Gitマスターを目指しましょう!
ガベージコレクションとは
まず初めに、git gc
のgc
にあたるガベージコレクション(Garbage Collection)について学びましょう。一般的なプログラミングにおけるガベージコレクションとは、プログラムが使用し終えたメモリ領域を自動で解放するプロセスです。
通常、プログラム実行にはメモリ領域を使用します。プログラム実行後、使用していたメモリ領域は解放されますが、一部のプログラムはメモリが解放されずに残ることがあります。そのメモリを定期的に解放することを、ガベージコレクションと呼びます。
一方で、Gitにおけるガベージコレクションは、gc
コマンドとは異なります。Gitリポジトリ内の未使用または一時的なオブジェクトを整理し、不要なデータを削除することでディスクスペースの使用を最適化します。
「git gc」について
git gc
コマンドは、Gitリポジトリのメンテナンスを目的としたガベージコレクションを行います。このコマンドは、リポジトリ内の使われていないオブジェクトの削除、リファレンスの整理、データの圧縮などを行い、リポジトリを最適化します。これにより、リポジトリのパフォーマンスが向上し、ディスクスペースが有効に活用されます。
「git gc」主な機能
-
不要なファイルやオブジェクトの削除
リポジトリ内で使われていない不要なファイルやオブジェクトを削除します。
-
リポジトリ内のオブジェクトを圧縮
複数のファイルを統合し、差分のみを保存したり、複数のオブジェクトを1つのファイル(パックファイル)にまとめて圧縮します。
-
リファレンスログの整理
リファレンスから到達不可能なコミットのログエントリを削除します。これにより、不要な情報がリポジトリから取り除かれます。
「git gc」の対象リポジトリ
git gc
コマンドは、主にローカルリポジトリで使用されるコマンドです。このコマンドを実行することで、ローカルリポジトリのメンテナンスを行い、リポジトリのパフォーマンスを向上させると同時に、使用しているPCのディスクスペースを節約します。
Git運用でよく使用されるコマンドとの併用
ガベージコレクションは、git commit
やgit merge
など、Git運用でよく使用されるコマンドと共に自動的に実行されることがあります。これは、auto gc
と呼ばれ、設定されている閾値を超えた不要なファイルが存在する場合に、git gc
が自動的に実行されます。実行の閾値はgc.auto
と gc.autopacklimit
のファイルによって設定されています。これらのコマンドを使用する度に、裏ではリポジトリ内のメンテナンスが行われている、ということがあるのです。
Gitリポジトリ内の不要なデータとは
長い間、開発が継続した大規模なGitリポジトリには、不要となる様々なデータが蓄積されていきます。不要データの例として、Gitでの切り離されたコミットなどが挙げられます。
切り離されたコミットとは、特定のブランチから切り離された状態でコミットが行われる物を指します。これは、ユーザーが誤ってブランチではなく、特定のコミットやタグに直接にチェックアウトした場合などに発生します。
例えば、過去のコミット内容を確認するために特定のコミットに直接移動したとします。これは、現在の作業ブランチのラインから離れ、移動したコミットの状態にHEAD
がポイントされます。この状況で新しいコミットを追加して作業を継続すると、そのコミットはどのブランチにも属さない状態になります。通常、コミットはブランチに属することで参照を通じアクセスしたり、履歴を追うことができます。切り離されたコミットはどのブランチからも参照されずに孤立するため、後にそのコミットを見つけることや、内容を把握することが難しくなります。このような孤立したり、ブランチから切り離されたコミットが不要データとしてリポジトリ内に蓄積していきます。
下記はブランチから切り離されたコミットができてしまう事例です。これは、コミットIDにチェックアウトすることで発生し、この操作はdetached HEAD
の状態になります。
コミットにチェックアウトした後も、コミットの登録を継続することができてしまいます。
コミットを継続した後にブランチを変更すると、それまで登録していたコミットが参照できなくなります。コミットはブランチに属することで参照できるためです。ブランチのないコミットは切り離されたコミットとなり、リポジトリ内の不要なデータとなってしまいます。
「git gc」コマンドの開発現場での活用例
git gc
コマンドは、Gitリポジトリのメンテナンスとパフォーマンスの最適化に欠かせないツールだということが分かりました。このコマンドは、特にリポジトリが大きくなりがちな大規模プロジェクトで、定期的に使用されています。以下に、どのようにしてgit gc
が活用され、開発効率を高めるのに役立つかを解説します。
リポジトリのパフォーマンスを維持
開発が進むにつれて、Gitのリポジトリにはコミット、ブランチ、タグなどが増え続け、リポジトリのサイズが大きくなります。このサイズの増加は、リポジトリでのコミットなどの実行時間を長くし、パフォーマンス低下の原因となります。git gc
を定期的に実行することで、リポジトリ内の不要なオブジェクトの削除や圧縮を行い、リポジトリのパフォーマンスを維持することができます。
ディスクスペースの最適化
大規模なプロジェクトや長期間にわたるプロジェクトでは、リポジトリのサイズが大きくなることが一般的です。不要になった切り離されたコミットなどが蓄積し、リポジトリに負荷がかかります。git gc
を使用してこれらの不要なデータをクリーンアップすることで、ディスクスペースをを有効に活用することができます。また、リポジトリのバックアッププロセスをより効率的に行うことが可能になります。
このようにgit gc
は、開発現場でリポジトリのパフォーマンス維持し、最適化を図るための非常に重要なツールです。適切に利用することで、Git リポジトリをクリーンに保ち、開発効率を向上させることができます。
「git gc」の使い方
この記事の冒頭でお話ししたような、Git操作のパフォーマンスが低下した場合、git gc
コマンドを活用することで、効率的にパフォーマンスを回復させることができます。
以下のコマンドは基本的な実行方法です。このコマンドを実行することで、不要なファイルやオブジェクトを削除し、データを効率的に圧縮することが可能です。
git gc
実行結果の検証
実際にgit gc
を実行した結果を見ていきましょう。以下はコマンドを実行した様子です。
git gc
Enumerating objects: 1028, done.
Counting objects: 100% (1028/1028), done.
Delta compression using up to 11 threads
Compressing objects: 100% (686/686), done.
Writing objects: 100% (1028/1028), done.
Total 1028 (delta 321), reused 127 (delta 27), pack-reused 0 (from 0)
git gc
コマンドの実行前後の結果から、以下のことが分かります.
-
.git ディレクトリのサイズ変化
実行した結果、データの容量が4.4MBから436KBに減少し、約1/10の容量を削減することができました。これは、リポジトリ内の不要なファイルやオブジェクトを効果的に圧縮し、クリーンアップされたことを示しています。.
git
ディレクトリ内のデータが大幅に最適化され、ディスク使用量を大きく削減することができました。※du -sh
はリポジトリ内の容量を調べるコマンドです。# 実行前 du -sh .git 4.4M .git # 実行後 du -sh .git 436K .git
-
リポジトリ全体のサイズ変化
実行した結果、データの容量が148MBから144MBに減少しました。全体的なリポジトリのサイズも減少していますが、この変化は
.git
ディレクトリの変化ほど顕著ではありません。これは、リポジトリ内の実際のワーキングディレクトリにはそれほど大きな変更がなかったことを示しています。微量ではありますが、データの最適化がされました。# 実行前 du -sh ./ 148M ./ # 実行後 du -sh ./ 144M ./
-
リポジトリの整理と最適化
実行した結果、パック外のオブジェクト数900個から0個、データ容量が4.11MiBから0bytesに減少しました。一方で、パックファイルのサイズは59.68KiBから170.9 KiBに増加しました。これは、分散していたオブジェクトが効率的に圧縮され、パックファイルとして一つのファイルにまとめられたことを示しています。※KiB、MiBはPCのストレージの容量を正確に表す際に使用される単位です。
# 実行前 git count-objects -vH count: 900 size: 4.11 MiB in-pack: 128 packs: 1 size-pack: 59.68 KiB prune-packable: 0 garbage: 0 size-garbage: 0 bytes # 実行後 git count-objects -vH count: 0 size: 0 bytes in-pack: 1028 packs: 1 size-pack: 170.90 KiB prune-packable: 0 garbage: 0 size-garbage: 0 bytes
これらの結果から、git gc
はリポジトリ内のデータを整理し、不要なディスクスペースの解放を行っていることが分かります。このような効果的なリポジトリのメンテナンスができるため、定期的にgit gc
を使用することで、パフォーマンスの維持が可能となります。
実行の注意点として、git gc
のプロセスはリポジトリのサイズによっては時間がかかる可能性があります。特に大規模なリポジトリでは、リポジトリの使用が一時的に制限されることがあるため、作業の少ない時間帯や、その日の作業完了後に実行すると良いでしょう。また、git gc
の実行に不安がある場合は、万が一に備えて、リポジトリのバックアップを取ることをお勧めします。
「git gc」のオプション紹介
git gc
コマンドは、その基本形だけでも効果的なメンテナンスを自動的に行いますが、特定の条件でコマンドを実行したい場合は、オプションを利用することで指定が可能となります。このセクションでは、git gc
の主要なオプションについて紹介し、それぞれのオプションがどのように役立つかを紹介します。これらのオプションを適切に使用することで、メンテナンスの効果を最大限に引き出すことが可能になります。
項目 | 説明 |
---|---|
--aggressive | より徹底的な圧縮を行い、積極的な最適化を実行 |
--auto | git gcをする必要があるかを確認 |
--prune=<date> | 指定した日付よりも古いデータを削除 |
--aggressive
より徹底的な圧縮を行い、積極的な最適化を実行します。このオプションを指定すると、最適化に時間がかかる可能性があるため、リポジトリのパフォーマンスが著しく低下している場合の使用が推奨されます。
git gc --aggressive
--auto
git gcをする必要があるかを確認します。コマンドの実行が必要ない場合は、何も処理されずに終了します。
git gc --auto
--prune=<date>
指定された日付以前の到達不能なオブジェクトを削除します。デフォルトでは2週間前のオブジェクトが削除されますが、このオプションを使用することでその期間を変更できます。
--prune=now
は到達不能なオブジェクトを直ぐに削除するという指定です。
git gc --prune=now
この記事で学んだこと
この記事を通じて、「git gc」に関連する様々な知識を得ることができました。ここで簡単に振り返ってみましょう。
「git gc」について
git gc
コマンドは、Gitリポジトリのメンテナンスと最適化に欠かせないツールです。定期的にガベージコレクションを行うことで、リポジトリのサイズを管理し、パフォーマンスを向上させることが可能です。特に大規模なプロジェクトやディスクスペースが限られている環境では、このコマンドが重要な役割を果たします。
「git gc」主な機能
-
不要なファイルやオブジェクトの削除
リポジトリ内の参照されていない、不要なファイルやオブジェクトを削除し整理します。
-
リポジトリ内のオブジェクトを圧縮
複数のパックファイルを統合し、効率的にオブジェクトを圧縮して保存します。
-
リファレンスログの整理
到達不可能になったコミットのログエントリを削除し、リファレンスログを最新の状態に保ちます。
この記事では「git gc」の基本や実際の利用法に至るまで、その活用法を詳しく解説してきました。ぜひこのコマンドを日々の学習に取り込み、実践を積んで理解を深めていきましょう。
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2024.05.06
Gitコマンドgit cherry-pickとは?かわいいコマンドに隠された便利な機能を解説!
cherry-pickは英語の慣用句で「良い所だけをつまみ食いする」という意味があります。その意味の通り、`git cherry-pick`は別ブランチから現在作業中のブランチへ、必要なコミットを取り込むことができます。
- git
2024.06.02
コードを書いたのが誰かわかる超便利コマンド「git blame」の使い方を解説
コードの変更を誰が行ったのか簡単に確認したい!という方向けに、この記事では「git blame」を解説します。
- git
2024.05.06
コミットの詳細情報を表示する「git show」とは?
この記事では「git show」の解説をします。
- git