LoginSignup
0

More than 1 year has passed since last update.

git addした日時をしらべる

Last updated at Posted at 2022-08-04

TL;DR

git addだけされて未コミットのファイル群がある場合、

Macの場合
ls -lT .git/objects/ | sort -k6

これで列挙されるディレクトリ群で、タイムスタンプが最新のものが、「最後にgit addした日時」である可能性が高い。

各ディレクトリ内のファイルはzlibで圧縮されているので、最新時刻のディレクトリ内のファイルを解凍した中身と、現在git add済みのファイルを比較して一致すれば間違いない。

背景

複数のGitリポジトリを1つのエディタで開いて色々と作業していた時に、git statusしたら、git addだけされて未コミットの状態(ステージングエリアに入っているだけ)のファイルがいくつか見つかりました。

そのファイルは読むためにエディタで開いていましたが、編集した記憶はありません。
以下のどっちなのか分からず、不安になりました。

  • 実は操作ミスで今日編集してaddしちゃった
  • かなり前にaddだけしてcommit忘れて放置しちゃった

ところが、git addした時刻って、gitの標準コマンドでは調べられないっぽいんですよね。お助けコマンドのgit reflogにも、reset記録は出てくるけどaddはノーマーク。

でも、条件によってはなんとか調べることができたので、一応メモとして書いておきます。

実演

.git/objects 内のディレクトリ群

.git配下のファイルを直接確認します。仕組みを理解しやすいために、git initから順番に実演します。
(シェルプロンプトはfish標準の「Informative Vcs」で、gitの状態が見やすくなっています。)

初期状態の.git/objects内には、info packの2ディレクトリがある。

~ $ mkdir repo
~ $ cd repo
~/repo $ git init
Initialized empty Git repository in /Users/the_red/repo/.git/
~/repo (main|✔) $ ls -l .git/objects/
total 0
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 pack

空ファイルを作ってみるが、これだけでは変わらず。

~/repo (main|✔) $ touch .gitignore
~/repo (main|…) $ ls -l .git/objects/
total 0
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 pack

git addしてみると、e6というフォルダが増えている!

~/repo (main|…) $ git add .
~/repo (main|●1) $ ls -l .git/objects/
total 0
drwxr-xr-x  3 the_red  staff  96  8  4 11:33 e6
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 pack

コミットしてみると、さらにフォルダが2つ増えた。
addとcommitのどちらの場合もフォルダが作られるようですね。
コミットのハッシュ値は44becd9なので、44ディレクトリがコミットに相当するよう。

~/repo (main|●1) $ git commit -m 'Initial commit'
INFO[0000] opening .                                    
INFO[0000] scan time: 301 microseconds                  
INFO[0000] No leaks found                               
[main (root-commit) 44becd9] Initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore
~/repo (main|✔) $ ls -l .git/objects/
total 0
drwxr-xr-x  3 the_red  staff  96  8  4 11:33 44
drwxr-xr-x  3 the_red  staff  96  8  4 11:33 82
drwxr-xr-x  3 the_red  staff  96  8  4 11:33 e6
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32 pack

しかし11:33のディレクトリが3つもあって、順番が分からない。秒まで知りたい。

Macでは-lTオプションを付けると秒まで出してくれる。
(Linuxでは--full-timeらしい)

~/repo (main|✔) $ ls -lT .git/objects/
total 0
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 44
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 82
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:25 2022 e6
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 pack
~/repo (main|✔) $ 

あとは、ディレクトリ順のソートを時系列にソートしたい。普通はディレクトリがもっともっと多いので、目視ではとても探せないので。
パイプでsort -k6を実行すると、スペース区切りで左から6番目の「8(月)」以降だけを見てソートしてくれる。

~/repo (main|✔) $ ls -lT .git/objects/ | sort -k6
total 0
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 pack
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:25 2022 e6
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 44
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 82

いい感じ!
ためしに、ファイルの中身を書き換えてまたaddしてみる。

~/repo (main|✔) $ echo .env >> .gitignore
~/repo (main|✚1) $ git add .
~/repo (main|●1) $ ls -lT .git/objects/ | sort -k6
total 0
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 pack
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:25 2022 e6
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 44
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 82
drwxr-xr-x  3 the_red  staff  96  8  4 11:40:27 2022 4c

最下部に、新しいディレクトリ4cってのが出来てますね。

ここまでで、以下の2点が確認できたことになります。

  • 最終のadd時刻は8/4 11:40:27 (4c)
  • コミット44becd9直前のadd時刻は8/4 11:33:25 (e6)
Macの場合
ls -lT .git/objects/ | sort -k6

これで列挙されるディレクトリ群で、タイムスタンプが最新のものが、「最後にgit addした日時」である可能性が高い。

ここまで確認すればほぼ十分な気はするけど、さすがにタイムスタンプだけでは不安だったりもするので、もう少し深堀りする方法も次に書きます。

.git/objects/**/ 内のファイル群

もっと確実に調べたいなら、該当ディレクトリ(今回は4c)内をさらに確認してあげると良い。

~/repo (main|●1) $ ls -lT .git/objects/4c/
total 8
-r--r--r--  1 the_red  staff  20  8  4 11:40:27 2022 49bd78f1d08f2bc09fa0bd8191ed38b7dce5e3

ファイルが1つある。
add済みのファイルが複数ある場合は、ここにも複数ファイルができる。
catで見てあげれば良いかと思いきや、、、

~/repo (main|●1) $ cat .git/objects/4c/49bd78f1d08f2bc09fa0bd8191ed38b7dce5e3
xK��OR0e�K�+�=v⏎                                                                                                                  

バイナリらしく、そのままでは見れない。
fileコマンドで正体を確認。

~/repo (main|●1) $ file .git/objects/4c/49bd78f1d08f2bc09fa0bd8191ed38b7dce5e3 
.git/objects/4c/49bd78f1d08f2bc09fa0bd8191ed38b7dce5e3: zlib compressed data

zlib形式で圧縮されたデータとのこと。

zipとかgzipならOS標準コマンドで解凍できるんだけど、
zlibを解凍するには、別途ツールが必要。僕はこれをインストールしました。

brew tap ebc-2in2crc/zlibcmd
brew install zlibcmd

これでzlibコマンドが使えるようになったので、解凍してみる。

~/repo (main|●1) $ cat .git/objects/4c/49bd78f1d08f2bc09fa0bd8191ed38b7dce5e3 | zlib --decompress
blob 5.env
  • blobがファイルタイプ、
  • 5が容量(改行入れて5バイト)
  • .envがファイルの中身

ですね。今回はこれで間違いない!
ちなみにファイル名.gitignoreは、別の場所で管理されています。

もっとちゃんとやろうとすると色々とあるんだろうけど、今回はこれくらいで止めておきますw

git gcには要注意

僕はほとんど使わないんですけど、git gcというコマンドで、
一時ファイルを綺麗に掃除してgitの動作を軽くすることができます。

これがまさに、今回調べた.git/objects配下を消すという行為なので、
git gcしてしまったら、この記事の調査方法は使えなくなりますのでご注意!
git reflogも使えなくなります)

~/repo (main|●1) $ ls -lT .git/objects/ | sort -k6
total 0
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 info
drwxr-xr-x  2 the_red  staff  64  8  4 11:32:35 2022 pack
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:25 2022 e6
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 44
drwxr-xr-x  3 the_red  staff  96  8  4 11:33:52 2022 82
drwxr-xr-x  3 the_red  staff  96  8  4 11:40:27 2022 4c
~/repo (main|●1) $ git gc
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Writing objects: 100% (4/4), done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
~/repo (main|●1) $ ls -lT .git/objects/ | sort -k6
total 0
drwxr-xr-x  4 the_red  staff  128  8  4 12:19:52 2022 info
drwxr-xr-x  4 the_red  staff  128  8  4 12:19:52 2022 pack

参考リンク

Gitのステージング領域の正体を探る
https://engineering.mercari.com/blog/entry/2017-04-06-171430/

ファイル時刻の秒単位まで取得
https://tech.withsin.net/2016/12/26/ls-full-time/

おわりに

冒頭に書いた疑問

  • 実は操作ミスで今日編集してaddしちゃった
  • かなり前にaddだけしてcommit忘れて放置しちゃった

は、後者であることが分かりました。
add分は念の為別ブランチに退避してGitHubでブランチをプロテクトして、
メインのブランチは最終コミットに戻して、安心して開発を再開できました。

ごくまれにこういうケースあると思うので、誰かの役に立てたら嬉しいっす。
ではまた〜。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0