0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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でブランチをプロテクトして、
メインのブランチは最終コミットに戻して、安心して開発を再開できました。

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

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?