📝

Bareリポジトリだけで編集を全部やる

2021/11/18に公開

概要

gitのbareリポジトリとはワーキングディレクトリを持たないリポジトリである。
このリポジトリに変更を加えたい場合は基本的にはnon bareリポジトリとしてcloneしてそのワーキングディレクトリ内のファイルを編集してコミットしてプッシュすると思う。

ただし今回はなぜかcloneをせずに全てbareリポジトリ上で作業を完結させたいという目的が発生したのでそれぞれの方法をまとめてみた

bare リポジトリの作成

--bare パラメータを付けてinitすると作成される

git init --bare <repo-name>.git

ブランチの作成

これは簡単
※commitが一つも無い状態だとエラーになるので注意

git branch new-branch-name

作成されたことを確認

$ git branch
  develop
* master

初回コミット(空コミット)

treeオブジェクトを作成

$ git write-tree
4b825dc642cb6eb9a060e54bf8d69288fbee4904

作成したtreeオブジェクトを元にcommitオブジェクトを作成

$ git commit-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 -m 'first commit'
5cbe1e2c54da44015b5b1ee3e6e56614bb2e6bc8

refs を更新する

git update-ref refs/heads/master 5cbe1e2c54da44015b5b1ee3e6e56614bb2e6bc8

ファイルの追加(更新)

追加するファイルを作成する

echo 'version1' > version.txt

ファイルオブジェクトを追加

git hash-object -w version.txt
5bdcfc19f119febc749eef9a9551bc335cb965e2

追加されたオブジェクトの中身を確認してみる

$ git cat-file -p 5bdcfc19f119febc749eef9a9551bc335cb965e2
version1

indexに追加する

git update-index --add --cacheinfo 100644 5bdcfc19f119febc749eef9a9551bc335cb965e2 version.txt

indexからtreeオブジェクトを作成する

$ git write-tree
5b931184deb66f3bed6c4379bfad773b1e65dd3a

上記で作成したtreeオブジェクトを元にcommitオブジェクトを作成、初期コミットとつなげたいので -p で親コミットを指定する

$ git commit-tree 5b931184deb66f3bed6c4379bfad773b1e65dd3a -m 'add version' -p 5cbe1e2c54da44015b5b1ee3e6e56614bb2e6bc8
76b1c8f63514249280853fabd5b143ad85a48172

作成したcommitオブジェクトを元にrefs を更新する

git update-ref refs/heads/master 76b1c8f63514249280853fabd5b143ad85a48172

ファイルの追加(フォルダ内ファイル)

ファイルの追加と大部分が被るので差分だけ。
update-indexに追加するパスにフォルダを含めるだけ。

git update-index --add --cacheinfo 100644 5bdcfc19f119febc749eef9a9551bc335cb965e2 test/version.txt

ファイル削除

ファイル削除はあらかじめcloneしたnon-bareリポジトリでファイルを追加してpushしておいた(file1.txt, file2.txt)(めんどくさかったので...)

HEADのcommitオブジェクトのハッシュを取得する

git rev-parse HEAD
aea7957d49a7d2e9515c569c146556bbb27171b2

commitオブジェクトに関連づくtreeオブジェクトのハッシュを確認する

git cat-file -p aea7957d49a7d2e9515c569c146556bbb27171b2
()
tree 561a7dd62dfb5fe3d7d8319e68dff75edf27064c
()

treeオブジェクトを元にindexに展開

git read-tree 561a7dd62dfb5fe3d7d8319e68dff75edf27064c

indexの内容を確認

$ git ls-files -s
100644 7284ab4d2836271d66b988ae7d037bd6ef0d5d15 0       file1.txt
100644 7284ab4d2836271d66b988ae7d037bd6ef0d5d15 0       file2.txt

今回はfile1.txtを削除する

git rm --cached file1.txt

indexを元にtreeオブジェクトを作成する

git write-tree
561a7dd62dfb5fe3d7d8319e68dff75edf27064c 

上記のtreeオブジェクトを元にcommitオブジェクトを作成する

git commit-tree 561a7dd62dfb5fe3d7d8319e68dff75edf27064c -m 'delete file1.txt' -p f2d7479
aea7957d49a7d2e9515c569c146556bbb27171b2

作成したcommitオブジェクトを元にrefs を更新する

git update-ref refs/heads/master aea7957d49a7d2e9515c569c146556bbb27171b2

ファイル移動(リネーム)

基本的に上記手順のファイル削除とファイル追加を合わせたような手順なので重要な部分だけ記載する。

indexの状態を確認する。これらの値は後で利用する。

$ git ls-files -s
100644 7284ab4d2836271d66b988ae7d037bd6ef0d5d15 0       file2.txt

file2.txtを一時的に削除

git rm --cached file2.txt

mode, hash 等は変えずにパスだけ変えて(file2.txt -> fileA.txt)indexに追加する

git update-index --add --cacheinfo 100644,7284ab4d2836271d66b988ae7d037bd6ef0d5d15,fileA.txt

indexを確認

$ git ls-files -s
100644 7284ab4d2836271d66b988ae7d037bd6ef0d5d15 0       fileA.txt

移行のツリーオブジェクト作成、コミットオブジェクト作成...は同じ手順なので省略

Discussion