t11hi

hene.dev

commit した日時を変更

commit した日時を変更する

変更したい理由

AtCoder で、コードを提出した後に commit し忘れることがある。 commit した日時を提出した日時に変更したい。

commit した日時を変更

下記のブログの内容を参考に使いやすいように調整しました。

調整内容

  • 引数がないときは、何もしない
  • mainmaster ブランチのときは、何もしない
  • 作業中でも日時を変更できる

コード

dotfiles/zsh/.my_functions/.giso.zshrc

# アリバイ工作
# * [Gitでアリバイ工作するスクリプトはコチラです - 銀の弾丸](https://takamints.hatenablog.jp/entry/and-then-you-disguise-the-authored-date)
#
# 使い方
# * $ giso '2021-08-15 20:30:00'

function giso() {
  # 引数がないときは、終了する
  if [[ $1 == "" ]]; then
    echo "Error: datetime need to be specified"
    return 1
  fi

  # main か master ブランチのときは、終了する
  local current_branch="$(git branch --contains | cut -d " " -f 2)"
  local array_main_branch=("main", "master")
  if [[ " ${array_main_branch[@]} " =~ " ${current_branch} " ]]; then
    echo "Error: please change from the $current_branch"
    return 1
  fi

  # 変更途中のものを stash する
  git stash save -u > /dev/null

  # AuthorDate を書き換え
  local giso_author_date="git commit --amend -C HEAD --date='$1'"
  echo "$ $giso_author_date"
  eval $giso_author_date

  echo ""

  # CommitDate を書き換え
  local giso_commiter_date="git rebase HEAD~ --committer-date-is-author-date"
  echo "$ $giso_commiter_date"
  eval $giso_commiter_date

  # stash したのを戻す
  git stash pop > /dev/null
}

使い方

$ pwd
/Users/user_name/dotfiles

# zsh/.my_functions/.giso.zshrc の読み込み
$ source zsh/.my_functions/.giso.zshrc

# AuthorDate, CommitDate の確認
$ git log --pretty=fuller
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
commit 4cfd1e9d81699f70ea039b4c0291913eea63be68 (HEAD -> feature/giso)          ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻
Author:     user_name <user_name@example.com>
AuthorDate: Sun Aug 15 22:03:43 2021 +0900
Commit:     user_name <user_name@example.com>
CommitDate: Sun Aug 15 22:03:43 2021 +0900

    :sparkles: Fix giso

# アリバイ工作(今回作ったコマンド)
$ giso '2021-08-15 22:00:00'
$ git commit --amend -C HEAD --date='2021-08-15 22:00:00'
[feature/giso 71f2002] :sparkles: Fix giso
 Date: Sun Aug 15 22:00:00 2021 +0900
 1 file changed, 1 insertion(+)

$ git rebase HEAD~ --committer-date-is-author-date
Current branch feature/giso is up to date, rebase forced.
Successfully rebased and updated refs/heads/feature/giso.

# AuthorDate, CommitDate が '2021-08-15 22:00:00' に変わっているのを確認
$ git log --pretty=fuller
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
commit 7956951f5fabdbb2ff0cc450fde4c0d4686d30eb (HEAD -> feature/giso)          ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻
Author:     user_name <user_name@example.com>
AuthorDate: Sun Aug 15 22:00:00 2021 +0900
Commit:     user_name <user_name@example.com>
CommitDate: Sun Aug 15 22:00:00 2021 +0900

    :sparkles: Fix giso

学び

AuthorDate と CommittDate

$ git commit --amend すると、ComitterDate が更新した日時になる。

# AuthorDate, CommitDate の確認
$ git log --pretty=fuller
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
commit ae2febf8df97cd7b20ae111dad48f4147d71cdbe (HEAD -> feature/giso)          ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻
Author:     user_name <user_name@example.com>
AuthorDate: Sun Aug 15 21:31:46 2021 +0900
Commit:     user_name <user_name@example.com>
CommitDate: Sun Aug 15 21:31:46 2021 +0900

    :recycle: Refactor giso

# AuthorDate のみ変更
$ git commit --amend -C HEAD --date='2021-08-15 21:31:00'
[feature/giso ebd6896] :recycle: Refactor giso
 Date: Sun Aug 15 21:31:00 2021 +0900
 1 file changed, 1 insertion(+)

# 現在時刻の確認
$ date
日  8 15 21:43:02 JST 2021

# AuthorDate が指定した時間に、CommitDate が更新した日時に変わっているのを確認
$ git log --pretty=fuller
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
commit d77d765d4824c6d1361621fe7e6dbe3042743852 (HEAD -> feature/giso)          ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻
Author:     user_name <user_name@example.com>
AuthorDate: Sun Aug 15 21:31:00 2021 +0900
Commit:     user_name <user_name@example.com>
CommitDate: Sun Aug 15 21:42:57 2021 +0900

    :recycle: Refactor giso

自分が今いるブランチを確認

# ブランチを確認
$ git branch --contains
* feature/giso

# * を消せる(今回はこちらを使いました)
$ git branch --contains | cut -d " " -f 2
feature/giso

main か master ブランチのときは、終了

master ブランチでコレやって、push -f とかしちゃったら、市中引き回しの上獄門ですから気をつけて。

Git でアリバイ工作するスクリプトはコチラです - 銀の弾丸

push -f してしまいそうなので、mainmaster ブランチのときは、何も実行せずに終了する。

  # main か master ブランチのときは、終了する
  local current_branch="$(git branch --contains | cut -d " " -f 2)"
  local array_main_branch=("main", "master")
  if [[ " ${array_main_branch[@]} " =~ " ${current_branch} " ]]; then
    echo "Error: please change from the $current_branch"
    return 1
  fi

標準出力を捨てる

$ git stash の標準出力を > /dev/null で捨てる。

他に作業中のファイルがあっても、giso コマンドは使いたいので、stash で一旦退避させてから戻す。

  # 変更途中のものを stash する
  git stash save -u > /dev/null

  # 略

  # stash したのを戻す
  git stash pop > /dev/null

標準出力の結果を変数に入れると色がつかない

git status

$ git status
On branch feature/git_status
Your branch and 'origin/main' have diverged,
and have 8 and 2 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        zsh/.my_functions/.git_status.zshrc

nothing added to commit but untracked files present (use "git add" to track)

色がつく

$ git status と同じ。

function _git_status_colored() {
  local test='git status'
  echo "$ $test"
  eval $test
}

_git_status_colored

色がつかない

function _git_status_not_colored() {
  local test='git status'
  echo "$ $test"
  echo "$(eval $test)"
}

_git_status_not_colored

エラー

最初、下記みたいな感じで書いて詰まってました。

TODO: ここは時間あるときに別で書きます。

function _git_status_error() {
  local test='git status'
  echo "$ $test"
  echo "$($test)"
}
$ _git_status_error
$ git status
_git_status_error:3: command not found: git status

参考