Git で管理しているファイルの変更追跡を一時的に無視したい

Git を使って開発しているプロジェクトで、トラブル対応や機能のテストのために一時的に変更を加えた状態で作業をしたい、ただし一時的な変更なのでコミットしたくないといったことがあります。このような場合に skip-worktree を使うと、変更の追跡を一時的に無視できます。

特定のオプションを有効にしている場合に発生する問題への対応のために設定ファイルを変更している、しかしオプションはコミットしない。そうそうあることでもないですが、このようなパターンで一部変更しながらもコミットしたくないというケースがあります。そして慎重に作業を進めつつも、うっかりコミットして面倒なことに。。。

最初からコミットするつもりがない変更については明示的に外してしまうのも手です。

環境
本記事の開発環境は以下となります。

  • Windows 10 64bit + WSL Ubuntu 18.04.1 LTS
  • Git 2.17.1 (WSL Ubuntu 18.04.1 LTS)

参考情報

git update-index –skip-worktree で無視

指定するパスを Git の変更追跡から無視する設定がgit update-index --skip-worktree <path>です。

このオプションを指定すると変更追跡から無視されるので、ファイルを更新しても Git の変更に乗りません。たとえば変更したファイルconfig.jsonがあったとします。Git で状態を見ると以下のようになります。

1
$ git status
2
ブランチ master
3
Your branch is up to date with 'origin/master'.
4
5
Changes not staged for commit:
6
  (use "git add <file>..." to update what will be committed)
7
  (use "git checkout -- <file>..." to discard changes in working directory)
8
9
        modified:   config.json
10
11
no changes added to commit (use "git add" and/or "git commit -a")

そこで変更追跡から無視して再度確認してみます。変更対象に入っていないことがわかります。

1
$ git update-index --skip-worktree config.json
2
$ git status
3
ブランチ master
4
Your branch is up to date with 'origin/master'.
5
6
nothing to commit, working tree clean

またskip-worktree設定しているファイルは以下のコマンドから確認できます。

1
$ git ls-files -v | grep ^S
2
S config.json

これにより誤りコミットを避けることができます。

変更管理対象に戻す

戻すためのオプションは--no-skip-worktreeです。最初にnoが入っています。

1
$ git update-index --no-skip-worktree config.json
2
$ git status
3
ブランチ master
4
Your branch is up to date with 'origin/master'.
5
6
Changes not staged for commit:
7
  (use "git add <file>..." to update what will be committed)
8
  (use "git checkout -- <file>..." to discard changes in working directory)
9
10
        modified:   config.json
11
12
no changes added to commit (use "git add" and/or "git commit -a")

リモートで更新された場合

変更追跡から無視している状態で、そのファイルがリモートで更新されたらどうなるでしょうか。

もし、まだ変更していない場合(無視する設定だけした)は、リモートの更新をマージできます。これは通常の Git 管理と変わらず特別なことは何もありません。

変更してた場合、残念ながらマージできません。いったん--no-skip-worktreeして、変更を stash するか、何らかの対応をします。


ちょっと変更をキープしながら、作業をしなければならない時などに便利です。

ただしリモートで変更されてしまうと結構手間なので、長期にわたって使うものではないかもしれません。なにしろローカルの変更があるのでマージできないというエラーが出るのにgit statusnothing to commit, working tree cleanって、無視設定したことを忘れてると混乱しますから。