git でファイルの名前を変更するときは、変更をコミットし、名前を変更してから名前を変更したファイルをステージングする必要があります。 Gitは、ファイルを新しい未追跡ファイルと見なすのではなく、内容からファイルを認識し、変更履歴を保存します。
しかし、今夜だけで、私はgit mv
に戻ってしまいました。
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
Finderでスタイルシートの名前をiphone.css
からmobile.css
に変更します。
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: css/iphone.css
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# css/mobile.css
そのため、gitはCSSファイルを1つ削除し、新しいファイルを追加したと考えます。私が欲しいものではありません、名前の変更を元に戻してgitに仕事をさせましょう。
> $ git reset HEAD .
Unstaged changes after reset:
M css/iphone.css
M index.html
始めたところに戻ります。
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
代わりにgit mv
を使用しましょう。
> $ git mv css/iphone.css css/mobile.css
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: css/iphone.css -> css/mobile.css
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: index.html
#
私たちは良いようです。それでは、Finderを使用したときにgitが名前の変更を初めて認識しなかったのはなぜですか?
git mv
の場合、- マニュアルページ は
インデックスは、正常に完了すると更新されます[....]
そのため、最初に(git add mobile.css
を使用して)自分でインデックスを更新する必要があります。しかしながらgit status
は引き続き2つの異なるファイルを表示します
$ git status
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
# new file: mobile.css
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: iphone.css
#
git commit --dry-run -a
を実行すると、期待どおりの結果が得られるため、異なる出力を取得できます
Tanascius@H181 /d/temp/blo (master)
$ git commit --dry-run -a
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
# renamed: iphone.css -> mobile.css
#
git status
とこれらの違いが見られる理由を正確に説明することはできませんgit commit --dry-run -a
ですが、ここに Linus からのヒントがあります
gitは内部的に「名前変更の検出」全体を気にしません。名前変更で行ったコミットは、その後使用するヒューリスティックとは完全に独立していますshow名前の変更。
dry-run
は実際の名前変更メカニズムを使用しますが、git status
はおそらく使用しません。
Gitが移動としてそれを認識する前に、2つの修正されたファイルをインデックスに追加しなければなりません。
mv old new
とgit mv old new
の唯一の違いは、git mvがファイルをインデックスに追加することです。
mv old new
そしてgit add -A
もうまくいったでしょう。
git add .
はインデックスに削除を追加するものではないため、単に使用することはできません。
一番いいのは自分で試してみることです。
mkdir test
cd test
git init
touch aaa.txt
git add .
git commit -a -m "New file"
mv aaa.txt bbb.txt
git add .
git status
git commit --dry-run -a
Git statusとgit commit --dry-run -aは、新しいファイル/ aaa.txtが削除されたときにgit statusがbbb.txtを表示し、--dry-runコマンドが実際の名前変更を表示するという2つの異なる結果を表示します。
~/test$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: bbb.txt
#
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: aaa.txt
#
/test$ git commit --dry-run -a
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: aaa.txt -> bbb.txt
#
さあ、チェックインしましょう。
git commit -a -m "Rename"
これで、ファイルの名前が実際に変更され、git statusに表示されている内容が間違っていることがわかります。
物語の教訓:ファイルの名前が変更されたかどうかわからない場合は、 "git commit --dry-run -a"を発行してください。ファイルの名前が変更されたことが表示されたら、問題ありません。
新しいファイルとgit add css/mobile.css
をgit rm css/iphone.css
する必要があるので、gitはそれを知っています。それからgit status
に同じ出力を表示します
あなたはそれをステータス出力(ファイルの新しい名前)ではっきりと見ることができます:
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
そして(古い名前):
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
舞台裏ではgit mv
はまさにそれをするラッパースクリプトに過ぎないと思います。インデックスからファイルを削除して別の名前で追加する
Gitの観点からあなたのファイルについて考えてみましょう。
Gitはあなたのファイルに関するいかなるメタデータも追跡しません。
あなたのリポジトリは(とりわけ)持っています
$ cd repo
$ ls
...
iphone.css
...
そしてそれはgitの制御下にあります。
$ git ls-files --error-unmatch iphone.css &>/dev/null && echo file is tracked
file is tracked
これをテストします。
$ touch newfile
$ git ls-files --error-unmatch newfile &>/dev/null && echo file is tracked
(no output, it is not tracked)
$ rm newfile
するとき
$ mv iphone.css mobile.css
Gitの観点からは、
そのため、gitはすでに認識しているファイル( iphone.css )と検出した新しいファイル( mobile.css )についてアドバイスしますが、ファイルがインデックス内にある場合、またはHEAD gitが始まります。内容を確認してください。
現時点では、 "iphone.cssの削除"も mobile.css もインデックスにはありません。
Iphone.cssの削除をインデックスに追加する
$ git rm iphone.css
gitは正確に何が起こったのかを教えてくれます:( iphone.css は削除されています。それ以上起こったことは何もありません)
それから新しいファイルを追加してください mobile.css
$ git add mobile.css
今回は削除と新規ファイルの両方がインデックスに登録されています。これでgitはコンテキストが同じであることを検出し、それを名前の変更として公開します。実際、ファイルが50%似ていれば、それを名前変更として検出します。これにより、操作を名前変更として維持しながら、 mobile.css を少し変更することができます。
これはgit diff
で再現可能です。ファイルがインデックスに登録されたので、--cached
を使用する必要があります。 mobile.css を少し編集し、それをインデックスに追加して、以下の違いを確認します。
$ git diff --cached
そして
$ git diff --cached -M
-M
は、git diff
の「名前の変更の検出」オプションです。 -M
は-M50%
を表します(50%以上の類似性はgitに名前の変更を表現させます)が、mobile.cssをたくさん編集する場合はこれを-M20%
(20%)に減らすことができます。
Git 1.7.xでは、以下のコマンドが役に立ちました。
git mv css/iphone.css css/mobile.css
git commit -m 'Rename folder.'
元のファイル(つまりcss/mobile.css)はすでにコミット済みファイルに含まれていたため、git addは必要ありませんでした。
Gitはそれを新しい追跡されていないファイルと見なすのではなく、内容からファイルを認識します。
それはあなたが間違ったところです。
それは あと あなたがファイルを追加しただけで、そのgitは内容からそれを認識するでしょう。
手順1:ファイルの名前をoldfileからnewfileに変更する
git mv #oldfile #newfile
ステップ2:git commitしてコメントを追加する
git commit -m "rename oldfile to newfile"
ステップ3:この変更をリモートサーバーにプッシュする
git Push Origin #localbranch:#remotebranch
あなたはあなたのFinder移動の結果を上演しませんでした。 Finderで移動してからgit add css/mobile.css ; git rm css/iphone.css
を実行した場合、gitは新しいファイルのハッシュを計算し、それからファイルのハッシュが一致することを認識します(したがって名前の変更です)。
あなたが本当に手動でファイルの名前を変更しなければならない場合、例えば。スクリプトを使ってたくさんのファイルの名前を一括して変更してから、git add -A .
を使ってもうまくいきました。
Xcodeユーザーの場合:Xcodeでファイルの名前を変更すると、バッジアイコンが追加に変わります。 XCodeを使ってコミットすると、実際には新しいファイルを作成して履歴を失います。
回避策は簡単ですが、Xcodeを使用してコミットする前に実行する必要があります。
改名:Project/OldName.h - > Project/NewName.h改名:Project/OldName.m - > Project/NewName.m
次にXCodeに戻ると、バッジがAからMに変更されたことがわかります。これは、xcodeを使用する際のさらなる変更をコミットするために節約されます。