Blog

gitコマンドを使わずにcommitしてみた

はじめに

はじめまして、ニフティの高垣です。

【筆者プロフィール】

  • 入社時期:2025年4月
  • 入社前のスキル:
    • PythonやReactを主に使用
    • gitを使ったチーム開発経験はハッカソン(2,3日程度)のみ
  • 現在の担当:第一開発チーム(ニフティトップページやニフくじなどを担当)

みなさんはGitを使って開発をしたことがありますか?Gitはファイルの変更履歴などを記録するバージョン管理システムです。もし一度でも使ったことがあるなら、「git add」「git commit」「git push」といったコマンドを、もはや指が覚えているかもしれません。

また、使ったことがない方にとっては、今後チームで開発する際の必須のツールとなります。そんな風に誰もが当たり前のように使っているこれらのコマンドですが、裏側で一体何が起きているのか、深く考えたことはありますか?

そこで、この記事ではGitコマンドを使用せずにcommitをする方法を紹介します。

このプロセスを通じて、Gitがどのように変更履歴を記録しているのか、その仕組みを理解する一助となれば幸いです。(Gitについてご存知ない方は弊社の新人研修の資料も併せてご覧ください)

一般的なcommitまでの流れ

一般的なcommitまでの流れは以下のようになります。

1. git init
2. ファイルの編集
3. git add (編集したファイル)
4. git commit

まずは、必要なファイルを用意するためにgit initします。その後、ファイルを編集し、git addで変更を知らせて、commitします。

今回は、こちらの手順を手動で行います。

実行環境

この記事で紹介するコマンド操作は、macOSを想定しています。

また、手順の途中でPythonGit(確認するために使用)が必要になるため、あらかじめインストールしておいてください。

Windowsをご利用の方へ

Windows環境で進める場合は、Git for Windowsに付属する「Git Bash」とPythonをインストールしていただくことで、同様の操作が可能です。

git init

git initとは

git initコマンドはGitで必要なリポジトリやファイルを作成するコマンドです。基本的には初回のみこのコマンドを使用します。

git initを実行すると.gitという隠しディレクトリが作成されます。このディレクトリの中でGitに関する全てのファイルを格納しています。

作成されるもの

具体的には以下のようなディレクトリを作成しています。

  • .git/hooks: 特定のGitイベントが発生した際に自動的に実行されるスクリプトを配置
  • .git/info:excludeを配置(gitで追跡されないルール)
  • .git/objects/: オブジェクト(後述)を配置
    • (/ハッシュ値の上2桁)
    • /info: 追加情報
    • /pack: パックファイルを配置する
  • .git/refs: 特定のコミットハッシュを指すポインタを保存する
    • /heads: ローカルリポジトリのブランチが指すコミットハッシュを格納
    • /remotes: リモートリポジトリのブランチが指すコミットハッシュを格納
    • /tags: タグの参照を格納
  • .git/logs: 各ブランチやHEADで実行したアクションを記録する

手順

では、さっそくgit initを手動で行なっていきます。

1.作業用のフォルダを作成します

2.作成したフォルダに移動します

3.Gitリポジトリの初期設定に必要なディレクトリ構造を作成します

.git/を作成した後は、configの設定と現在のブランチを設定します。

configでは、ファイルの実行権限の変更を追跡するかどうか、ファイル名の大文字・小文字を区別するかどうかなどを設定します。

4..git/configを作成し必要な情報を記述します

$ cat <<EOF > .git/configを実行した後以下をコピペしてください。

5..git/HEADを作成し、mainブランチをHEADにします

git statusコマンドを使用して、ここまで上手く行けているかどうか確認してみましょう。

上記が表示されたらOKです。

(補足: git initをすると実際にはhookのサンプルも生成されますが、今回は必要ないため省略しています)

commit

commitの仕組みについて

続いてcommitをしていきますが、その前にcommitの仕組みについて説明します。

commitをする際、

  • コミットメッセージ
  • タイムスタンプ
  • コミットを作成した人物の情報
  • コミットした人物の情報
  • ファイルの差分
  • コミット時点でのディレクトリの階層構造と全ファイル(treeオブジェクト)

などの情報を保存する必要があります。Gitでは、これら全てをまとめてコミットオブジェクトとして管理しています。コミットオブジェクトは一意に識別するためにハッシュ値(SHA-1)を生成し、それをキーとしています。(この仕組みをコンテンツアドレスストレージと呼びます)

コミットオブジェクトはディレクトリの階層構造や全ファイルの情報を毎回保存します。そのため、Gitにおけるcommitとはファイルの「差分」を記録するのではなく、リポジトリの「スナップショット」を記録しています。

commitの流れ

大まかなcommitの流れは、

1. ファイル内容をGitが管理できる形に変換する(BLOBの作成)
2.インデックスファイルの作成
3. treeオブジェクトを作成
4. コミットオブジェクトを作成
5. HEADにハッシュ値を登録

となっています。

インデックスファイルの作成が、git addに該当し、それ以降がgit commitに該当します。

コミットオブジェクトを作成するだけでは、現在のブランチで一番最新のコミットがどれなのかわからないため、Gitに知らせる必要があります。

そこで、.git/refs/headsにコミットオブジェクトのハッシュ値を保存します。これにより、最新のコミットを一意に特定することができます。

また、BLOB・インデックスファイル・treeオブジェクト・コミットオブジェクトの作成は次の図ような手順で作成されます。

先ほど、Gitにおけるcommitとはリポジトリの「スナップショット」を記録していると述べましたが、そのまま保存するのはあまり賢い方法ではありません。

そこで、オブジェクトを圧縮することで容量を効率的に消費しています。

commitの手順

それでは、今回の目玉であるcommitをしていきます。

1.適当なファイルを追加します(例としてexample.txtを作成)

2.コミットオブジェクトの作成

先ほどの図を見ると、BLOB・treeオブジェクト・コミットオブジェクトの作成手順は基本的に共通しています。また、それぞれの工程で前のステップで生成したハッシュ値が必要となります。
そこで今回は、これら一連の流れを自動化できるよう、コミットオブジェクトを作成するシェルスクリプトを作成しました。

以下のシェルスプリクトをcommit.shとして保存してください。

シェルスクリプトに実行権限を与えてください

第1引数に編集したファイル、第2引数にコミットメッセージを入力して実行してください

完了するとそれぞれのハッシュ値が表示されます。このうち、コミットオブジェクトのハッシュ値をGitに知らせます。

3.HEADにハッシュ値を登録します

4.commitできたか確認します

ハッシュ値やAuthorが表示されていれば完了です。お疲れ様でした!!

補足

今回は、BLOBを作成した後にインデックスファイルを作成しましたが、インデックスファイルを作成せずに、コミットオブジェクトを作成することも可能です。その場合に、面白い挙動が見られますので、シェルスクリプトを変更してぜひチャレンジしてみてください。

終わりに

今回は、手動でcommitをしてみました。Gitは非常に便利なツールであり、普段何気なく使っているコマンドは、私たちの代わりに複雑な処理を自動で実行してくれます。しかし、その裏側にある論理的な仕組みを理解することは単なる豆知識ではありません。これはGitに限らず、あらゆるツールに共通することであり、本質的な理解やトラブルシュートの力につながります。

この記事が、普段は意識しない部分にも目を向けるきっかけとなり、技術への理解をより深めるきっかけとなれば幸いです。

この記事を読んだ学生さんに向けて

入社して約4ヶ月ですが、弊社は本当に様々なことに挑戦できる環境だと感じています。

私の場合は新しいインフラ環境の構築や、企画会議でのファシリテーターなどに取り組みました。これらは全て初挑戦でしたが、どの場面でも周囲の手厚いサポートがあり、大きく成長できたと実感しています。

様々な技術に触れてみたい方、開発だけでなく企画にも参加してみたい方にとっては、弊社は非常に魅力的な環境だと思います。

また、弊社の新人研修で使用している資料も公開していますので、興味のある方はぜひこちらもご覧ください。

次は、大型新人のパクさんの記事です。
どうぞご期待ください。

参考文献

https://drew.silcock.dev/blog/artisanal-git/

Git

ニフティでは、
さまざまなプロダクトへ挑戦する
エンジニアを絶賛募集中です!
ご興味のある方は以下の採用サイトより
お気軽にご連絡ください!

ニフティに興味をお持ちの方は
キャリア登録をぜひお願いいたします!

connpassでニフティグループに
参加いただくと
イベントの
お知らせが届きます!