2017年07月22日

git ファイルの追跡

ファイルの追加


新たなファイルを追加する場合は、
作業ツリー上に対象ファイルを追加したら、ステージし、コミットすればよい。
$ echo "aaa" > a.txt
$ git add a.txt
$ git commit -m "Add new file : a.txt"
[master (root-commit) ebd2002] Add new file : a.txt
1 file changed, 1 insertion(+)
create mode 100644 a.txt


作業ツリーは、ディレクトリを追加し階層構造にすることも可能。
$ mkdir nextdir
$ cd nextdir/
$ echo "bbb" > b.txt
$ git add b.txt
$ git commit -m "Add new file : b.txt"
[master b60971b] Add new file : b.txt
1 file changed, 1 insertion(+)
create mode 100644 nextdir/b.txt


追跡対象ファイルを一覧を確認してみると、

$ git ls-files

a.txt
nextdir/b.txt

階層構造でファイルが追跡できていることがわかる。


ただし、空のディレクトリだけではgit管理下に入らない。
何らかのファイルを置く必要がある。慣習的に ".gitkeep" という空ファイルを置くことが多い。



いつ追跡が開始されるのか


git add により、一度ステージされるとファイルが追跡対象となる。
$ echo "ccc" > c.txt
$ git add c.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD ..." to unstage)

new file: c.txt

"c.txt" を作成し、ステージした。

ここで、ファイルを確認してみる。
$ git ls-files
a.txt
c.txt
nextdir/b.txt

追跡対象のファイルに、"c.txt" が含まれている。

もう1つファイルを作成した後で、追跡対象ファイルを確認してみる。
$ echo "ddd" > d.txt
$ git ls-files
a.txt
c.txt
nextdir/b.txt

"d.txt" はまだ対象になっていない。

追跡されていないファイルの一覧を表示して確認してみる。
-o オプションを使う。

$ git ls-files -o

d.txt

追跡対象外のファイルとして表示された。git add する前はまだ追跡対象になっていないことがわかる。





ファイルの削除


不要となったファイルを追跡から外す。
git rm した後に、コミットする。

$ git rm c.txt
$ git commit -m "Delete file : c.txt"

[master 87816aa] Delete file : c.txt
1 file changed, 1 deletion(-)
delete mode 100644 c.txt


ディレクトリごとすべて削除する場合は、ディレクトリを指定することと、-r オプションを指定する。

$ git rm -r nextdir/
$ git commit -m "Delete files"

[master 0ba11c3] Delete files
3 files changed, 3 deletions(-)
delete mode 100644 nextdir/b.txt
delete mode 100644 nextdir/e.txt
delete mode 100644 nextdir/f.txt



作業ツリー上にファイルを残しつつ、追跡対象から外す場合は、--cached オプションを使う。

$ git rm --cached d.txt
$ git commit -m "Untracked files : d.txt"

[master bdf7fa7] Untracked files : d.txt
1 file changed, 1 deletion(-)
delete mode 100644 d.txt







ファイルの移動


作業するファイル数が増加してくると、ファイルをグループ化して管理するほうがわかりやすい。また間違ったディレクトリに作成してしまうこともある。
このような場合にファイルの配置を移動させる。
git mv した後に、コミットする。
$ git ls-files
a.txt
c.txt
d.txt
nextdir/b.txt

$ git mv d.txt ./nextdir/
$ git commit -m "move file d.txt -> next/d.txt"

[master 099158f] move file d.txt -> next/d.txt
1 file changed, 0 insertions(+), 0 deletions(-)
rename d.txt => nextdir/d.txt (100%)

$ git ls-files
a.txt
c.txt
nextdir/b.txt
nextdir/d.txt




git mv は、ファイル名の変更もできる。

$ git mv c.txt c_new.txt
$ git commit -m "rename c.txt -> c_new.txt"

[master 0aa0120] rename c.txt -> c_new.txt
1 file changed, 0 insertions(+), 0 deletions(-)
rename c.txt => c_new.txt (100%)

$ git ls-files
a.txt
c_new.txt
nextdir/b.txt
nextdir/d.txt




ここで、リネームしたファイルのログを確認してみる。
$ git log --oneline c_new.txt
0aa0120 rename c.txt -> c_new.txt

通常のログ確認では、リネームした以降のコミット履歴しか見れなくなっていた。



もし変更履歴が積み重なっているファイルの場合は、履歴が追えなくて困る。
リネーム前の履歴も見たければ--follow オプションを使う。

$ git log --follow --oneline c_new.txt

0aa0120 rename c.txt -> c_new.txt
947cfa3 Add new file : c.txt






git管理させないファイルを無視させる


プロジェクト単位で無視する


".gitignore" ファイルを作成し作業ツリーに配置する。
$ vi .gitignore


中身はこのような感じ。
# テキストファイルを無視する
*.txt

#tempディレクトリ以下は全て無視
temp/

#readme.txt は git管理下
!readme.txt

  • ".gitignore" は複数のディレクトリに配置できる
  • ".gitignore" が配置されたディレクトリのサブディレクトも適用される。
  • 深い階層に置かれた ".gitignore" が後から解釈されるため、マッチングの優先度が高い
  • ファイルに記述されたパターンの上の行から順に解釈されるので、複数マッチする場合は、最後にマッチするパターンが適用される
  • #(ハッシュ記号)で始まる行はコメントとして扱う
  • 空行は無視
  • /(スラッシュ)で終わる場合はディレクトリを示し、対象ディレクトリに含まれるファイルすべてが無視される
  • ! マークで始まる行は以降のパターンで示される対象を無視しない


以下のようなファイル構成の場合に、
├ .gitignore
├ a.txt
├ index.html
├ log
│ └ .gitkeep
├ nextdir
│ ├ b.txt
│ └ readme.txt
└ temp
└ temp.html

git add .追跡ファイルを登録してみると、
$ git ls-files
.gitignore
index.html
log/.gitkeep
nextdir/readme.txt

"temp" ディレクトリは無視されている。テキストファイルは無視されているが "readme.txt" だけは追加されている。".gitignore" ファイルも追加されている。

これをコミットし、リモートリポジトリへ push すれば、リポジトリで共有するメンバーすべてで無視することができる。



以下のような構成があり、"log/" 以下はすべて無視したいが、".gitkeep" だけは例外として許可したい場合にどう書くか?
├ log
├ .gitkeep
├ a.log
└ b.log

以下は、間違い。
log/
!log/.gitkeep

ディレクトリ全体を無視した場合、そのディレクトリ内の一部のファイルを無視しないようにすることはできない。
※Git 2.7.0 で機能修正されたが、うまく動かないため、Git 2.7.1で revert されている。

正しくは以下のように設定する。
log/*
!log/.gitkeep





自分の環境だけで無視する


プロジェクトで共通の無視ファイルを準備するには、".gitignore" を使えばよいが、
例えば「自分の環境では、エディタの設定でバックアップファイルの自動作成を有効としているので、自動的にファイルが作られる。このバックアップファイルを無視するようにしたい」と言った場合は、
".git/info/exclude" に記述すればよい。
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

#エディタのバックアップファイルを無視
*.bak

こうしておけば、リポジトリで共有することはないので、メンバーごとの環境に合わせて無視ファイルを設定できる。





リポジトリに依存せず無視する


上記2つのやり方は、どちらもリポジトリに依存していた。
自分のマシン(PC)では、複数のプロジェクト(リポジトリ)を扱っていて、共通で無視ファイルを設定したい場合、global な gitignore を設定する。
gitignore ファイルを用意し、git config で準備したファイルのパスを設定する。

$ git config --global core.excludesfile $HOME/.gitignore_global


自分の環境設定に依存した無視ファイルを設定できる。".git/info/exclude" だとすべてのリポジトリで設定する必要があるので、自分の環境依存であれば、こちらに設定するほうが良い。




無視ファイルの注意点


無視ファイルで設定する前に、git add して、すでにgit管理下に入ったファイルは、".gitignore" で設定しても追跡対象からは外れない。

そのような場合は git rm で削除してから、追加する。
ファイルを残して、git管理から削除するには、--cached オプションを使う

$ git rm --cached d.txt







まとめ


作業していると後から関連ファイルをまとめておこうと思ったり、ファイル名を統一しようと思ったりすることもある。そのような場合に、gitで管理しているものをどうしたらいいのだろうかと疑問に思うことがあったので整理して再確認した。
ファイルの変更はいつも発生するわけではないが、"gitignore" の設定は必要。こちらのほうが必要な知識だと思う。



gitをインストール
gitサーバーのセットアップ
git ブランチについて
git 変更を一時的に退避 stash
git ブランチを合流するマージ
git ブランチを付け替える
git コミット履歴を変更する
git 変更をリセットする
git リモートでの操作
git リリース準備
git リモートブランチを追加
git チェックアウトをもっと便利に使う
git プロジェクトの構成
git 変更をpatchファイルにする
git コンフリクトに対処する
git 失敗したときの復元
posted by Zorinos at 20:00| Comment(0) | Linux | 更新情報をチェックする
この記事へのコメント
コメントを書く
コチラをクリックしてください