3
4

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 3 years have passed since last update.

gitのコミット日時をファイルの更新日時と一致させる方法

Posted at

はじめに

ファイル整理をしていて、過去のプロジェクトをgitで管理したいと思った。
だけど、ファイルの更新日時がすべて管理した日になるのは、なんかもったいない。
なので、あくまでもコミットしたのはその過去更新した日にしたいと思ったのがきっかけでいろいろ調べて、うまくいったので投稿した。

今回使用したスクリプトファイルはすべて、スクリプト集(github)に管理しているので、ここの説明を見るのが億劫な場合は、いきなりコードを見て、実行してみてもいいです。

目次

  1. 前準備
  2. 最終的なコマンド
    (細かい説明を見たくない場合は、ここだけ見てください。)
  3. 試行錯誤
  4. 参考文献

前準備

前提条件

試した環境

OS
windows10 Pro
必須ソフトウェア
git for windows(git bash付き)

おそらくできるであろう環境

OS
linux, mac, windows10
必須ソフトウェア
何らかのgit
linuxコマンドのdateコマンドが機能するターミナル

gitのインストール方法

windows10

今回のメインではないので、詳しい説明は省きますが、いまさらGit for Windowsのインストール、GitHubに接続してみた。に書いてある通り、インストールすれば、git bashも一緒にインストールされるはずです。

mac

触ったことがなく、あまり知らないので、ご容赦ください。
以下のサイトが参考になるかもしれません。

linux(ubuntu18.04LTS)

大体はプリインストールされています。
インストールされていない場合は、以下のコマンドをターミナルで打てば、インストールできると思います。
他のディストリビューションに関しては、触ったことがないので、ご容赦ください。
インストールされていない場合は、すいませんが、検索してください。

$ sudo apt install git

使用するコマンドの説明

今回かなり回りくどく、普通の使い方ではない使い方をしようとしているので、いろいろとコマンドが複雑に絡み合い、難しくなってしまっているため、今回使用したコマンドの中で、意味が分かっていた方がいいと思うコマンドの意味を紹介します。

GIT_COMMITTER_DATE=\"<date>\" git commit --allow-empty -m "<comment>" --date "<date>"

gitの初期コミット時に空のコミットをするためのコマンド
さらに、そのコミット日時を<date>にする。

GIT_COMMITTER_DATE=\"<date>\" git commit -m "<comment>" --date "<date>"

gitのコミットをするためのコマンド
さらに、そのコミット日時を<date>にする。

date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z'

ファイルの更新日のみを表示するコマンド
lsコマンドでも、ファイルの更新日は表示可能だが、その後につなげにくいので、dateコマンドを使用

ls -1atrd $(find "$(pwd)" -type f) | head -1

現在いるフォルダ配下のすべてのファイルの更新日の中で、一番古い更新日のファイルを出力するコマンド。
head -1は一行目を抜き出すだけのコマンド。
よって、ls -1atrd $(find "$(pwd)" -type f)がこのコマンドの重要な部分です。
これに関しては、以下の参考サイトに書いてあることを組み合わせたものです。

git rev-parse --show-toplevel

gitレポジトリのルートディレクトリを表示してくれるコマンドです。
つまり、.gitディレクトリが存在するディレクトリの名前を示します。

git ls-files "<filename>" --full-name

ファイル<filename>が、git管理化にあるファイルであれば、先ほどのルートディレクトリからの相対パスを表示します。
今回は、これを逆手に取り、git addできない.gitignoreで除外されたファイルを特定するのに使用しました。
つまり、このコマンドの表示がファイル名であれば、除外されていないファイルなので、コミットできるようにしました。

最終的なコマンド

基本方針はコミット日時をファイルの更新日に上書きしてしまうという方針です。
この方針で、ファイルの更新日にコミットの日時を合わせる場合は、以下のコマンドでできます。
また、以下のコマンドを利用したスクリプト(bash スクリプト)はスクリプト集(github)で管理しているので、よければ、参照してください。

複数ファイル(ディレクトリ)

以下のbashファイルは新規作成でも、既存レポジトリ使用する場合でも使えます。
gitで管理したいディレクトリのルートディレクトリでこのスクリプトを実行すれば完了
ただし、コミットの数は、ファイルの数だけになり、多くなってしまいます。

#!/bin/bash
IFS=$'\n'
root_dir=$(git rev-parse --show-toplevel 2>tmp.txt)
rm tmp.txt
if [ -z "$root_dir" ]; then
    git init
fi
pushd "$root_dir" || exit
file_list=$(find "$(pwd)" -type f -not -path "*/.git/*")
is_first_commit=$(git branch)
if [ -z "$is_first_commit" ]; then
    oldest_file_name=$(ls -1atrd $file_list | head -1)
    date_info=$(date -r "$oldest_file_name" '+%Y-%m-%dT%H:%M:%S%z')
    GIT_COMMITTER_DATE=\"$date_info\" git commit --allow-empty -m "first commit" --date "$date_info"
fi

old_file_list=$(ls -1atrd $file_list)
for file in ${old_file_list}; do
    echo "$file"
    base_name=$(basename "$file")
    dir_name=$(dirname "$file")
    pushd "$dir_name" || exit
    date_info=$(date -r "$base_name" '+%Y-%m-%dT%H:%M:%S%z')
    git add "$base_name"
    git_relative_path=$(git ls-files "$base_name" --full-name)
    popd || exit
    if [ -f "$git_relative_path" ]; then
        GIT_COMMITTER_DATE=\"$date_info\" git commit -m "feat: add $git_relative_path" --date "$date_info"
    fi
done
popd || exit

単一ファイル

コミットに上書き

GIT_COMMITTER_DATE=\"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\" git commit --amend --date \"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\"

新たなコミット作成

GIT_COMMITTER_DATE=\"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\" git commit --date \"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\"

空コミットの場合(初期コミット)

GIT_COMMITTER_DATE=\"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\" git commit --allow-empty --date \"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\"

空コミットを上書き(初期コミット)

GIT_COMMITTER_DATE=\"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\" git commit --allow-empty --amend --date \"$(date -r "<filename>" '+%Y-%m-%dT%H:%M:%S%z')\"

試行錯誤

ここは、僕の今回のコマンドにたどり着くまでの思考の変遷をメモしたものなので、本当に読み飛ばして構いません。

システムの時刻をいじる

参考文献のGitがファイルの日付を管理しない問題を何とかしたい(1)
を最初に見つけ、まさにやりたいことはこれだったが、システムの時刻を変更するのは抵抗があったので、やりませんでした。
この参考文献にあったgitにだけ時刻をファイル更新日に認識できるようにしたいとかんがえました。

gitにだけシステムの時刻が違うように見せたい

残念ながら、僕の検索能力、技術力では、直接それを行う方法は見つけられませんでした。
そこで、検索しているうちに偶然見つけたGitのコミット日時を上書きする2つの方法というサイトから
発想を転換して、コミットした後に書き換えてしまえればいいのではないかと考えました。
なので、この記事で紹介するコマンドは端的に言えば、ファイルの更新日になるようにコミット日時を上書きしたいというのが基本方針です。

参考文献

3
4
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
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?