私が理解していることから、Gitはファイルの名前変更/移動/コピー操作を実際に追跡する必要がないので、git mvの本当の目的は何ですか?マニュアルページは特に説明的ではありません...
時代遅れですか?これは内部コマンドであり、通常のユーザーが使用するためのものではありませんか?
私が理解していることから、Gitはファイルの名前変更/移動/コピー操作を実際に追跡する必要がないので、git mvの本当の目的は何ですか?マニュアルページは特に説明的ではありません...
時代遅れですか?これは内部コマンドであり、通常のユーザーが使用するためのものではありませんか?
回答:
git mv oldname newname
以下の略記です:
mv oldname newname
git add newname
git rm oldname
つまり、古いパスと新しいパスの両方のインデックスを自動的に更新します。
mv oldname newname; git add newname; git rm oldname
、それも失敗しますgit mv oldname newname
(この回答を参照)。
git mv
は少し異なることに注意してください。mv oldname newname; git add newname; git rm oldname
ファイルを変更する前にファイルに変更を加えたgit mv
場合、それらの変更はgit add
新しいファイルが作成されるまでステージングされません。
公式GitFaqから:
Gitには名前変更コマンドが
git mv
ありますが、これは便利です。この効果は、ファイルを削除して、名前が同じで内容が同じである別のファイルを追加することと区別がつかない
git mv
と手動のアプローチとの間の同等性を説明する公式のリファレンス(つまり、FAQよりも推力に値する)はありますか?からは明らかではありませんgit help mv
。
Gitは、あなたが何をしようとしているのかを推測しようとしています。それは、壊れていない歴史を保存しようとするあらゆる試みをしています。もちろん、完璧ではありません。そのgit mv
ため、意図を明示し、いくつかのエラーを回避できます。
この例を考えてみましょう。空のリポジトリから始めて、
git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
mv a c
mv b a
git status
結果:
# On branch master
# 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)
#
# modified: a
# deleted: b
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# c
no changes added to commit (use "git add" and/or "git commit -a")
自動検出に失敗しました :(またはそれをしましたか?
$ git add *
$ git commit -m "change"
$ git log c
commit 0c5425be1121c20cc45df04734398dfbac689c39
Author: Sergey Orshanskiy <*****@gmail.com>
Date: Sat Oct 12 00:24:56 2013 -0400
change
その後
$ git log --follow c
Author: Sergey Orshanskiy <*****@gmail.com>
Date: Sat Oct 12 00:24:56 2013 -0400
change
commit 50c2a4604a27be2a1f4b95399d5e0f96c3dbf70a
Author: Sergey Orshanskiy <*****@gmail.com>
Date: Sat Oct 12 00:24:45 2013 -0400
initial commit
ここで代わりに試してください(.git
実験するときは必ずフォルダを削除してください)。
git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
git mv a c
git status
ここまでは順調ですね:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: a -> c
git mv b a
git status
今、誰も完璧ではありません:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a
# deleted: b
# new file: c
#
本当に?しかし、もちろん...
git add *
git commit -m "change"
git log c
git log --follow c
...結果は上記と同じ--follow
です。完全な履歴のみが表示されます。
どちらのオプションでも奇妙な効果が生じる可能性があるため、名前の変更には注意してください。例:
git init
echo "First" >a
git add a
git commit -m "initial a"
echo "Second" >b
git add b
git commit -m "initial b"
git mv a c
git commit -m "first move"
git mv b a
git commit -m "second move"
git log --follow a
commit 81b80f5690deec1864ebff294f875980216a059d
Author: Sergey Orshanskiy <*****@gmail.com>
Date: Sat Oct 12 00:35:58 2013 -0400
second move
commit f284fba9dc8455295b1abdaae9cc6ee941b66e7f
Author: Sergey Orshanskiy <*****@gmail.com>
Date: Sat Oct 12 00:34:54 2013 -0400
initial b
それと比較してください:
git init
echo "First" >a
git add a
git commit -m "initial a"
echo "Second" >b
git add b
git commit -m "initial b"
git mv a c
git mv b a
git commit -m "both moves at the same time"
git log --follow a
結果:
commit 84bf29b01f32ea6b746857e0d8401654c4413ecd
Author: Sergey Orshanskiy <*****@gmail.com>
Date: Sat Oct 12 00:37:13 2013 -0400
both moves at the same time
commit ec0de3c5358758ffda462913f6e6294731400455
Author: Sergey Orshanskiy <*****@gmail.com>
Date: Sat Oct 12 00:36:52 2013 -0400
initial a
UPSは...今、歴史はに戻って起こっている初期の代わりに、初期B間違っています、。したがって、一度に2つの動作を実行すると、Gitが混乱し、変更を適切に追跡できなくなりました。ちなみに、私の実験では、を使用する代わりにファイルを削除/作成したときにも同じことが起こりましたgit mv
。注意して続行してください。あなたは警告されました...
@Charlesが言うように、git mv
は省略形です。
ここでの本当の質問は、「他のバージョン管理システム(SubversionやPerforceなど)はファイル名の変更を特別に扱います。なぜGitを使わないのですか?」です。
Linusはhttp://permalink.gmane.org/gmane.comp.version-control.git/217で特徴的なタクトについて説明しています:
この「トラックファイル」のがらくたを停止してください。Gitは重要なもの、つまり「ファイルのコレクション」を正確に追跡します。他には何も関係がなく、それが関係があると考えていても、 あなたの世界観を制限するだけです。CVSの「注釈」の概念が常に人々の使用方法を常に制限してしまうことに注意してください。私はそれは全く役に立たないがらくたの一部であると思います、そして私が百万倍より有用であると思う何かを説明しました、そして私が私の考えを世界の間違ったモデルに限定しないのでそれはすべて正確に落ちました 。
git mv
上で言及されていない別の使い方があります。
git add -p
(git addのパッチモード。http://git-scm.com/docs/git-addを参照)を発見したので、それを使用して、インデックスに追加した変更を確認します。したがって、私のワークフローは、(1)コードの作業、(2)レビューとインデックスへの追加、(3)コミットになります。
どのgit mv
ように適合しますか?ファイルを直接移動してgit rm
からとを使用するとgit add
、すべての変更がインデックスに追加され、変更を表示するためのgit diffの使用は(コミットする前に)簡単ではなくなります。git mv
ただし、を使用すると、インデックスに新しいパスが追加されますが、ファイルに加えられた変更は追加されないため、git diff
およびgit add -p
は通常どおり機能します。
git mv
非常に便利なニッチなケースがあります。大文字と小文字を区別しないファイルシステムでファイル名の大文字と小文字を変更したい場合です。APFS(mac)とNTFS(windows)は、デフォルトで大文字と小文字を区別しません(ただし、大文字と小文字を区別します)。
greg.kindelは、CBベイリーの回答に対するコメントでこれについて言及しています。
Macで作業していて、Mytest.txt
gitで管理されているファイルがあるとします。ファイル名をに変更しますMyTest.txt
。
あなたは試すことができます:
$ mv Mytest.txt MyTest.txt
overwrite MyTest.txt? (y/n [n]) y
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
まあ。Gitは、ファイルに変更があったことを認めません。
あなたは可能性があり、それをバックリネーム後、完全にファイルの名前を変更してでこの問題を回避します:
$ mv Mytest.txt temp.txt
$ git rm Mytest.txt
rm 'Mytest.txt'
$ mv temp.txt MyTest.txt
$ git add MyTest.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: Mytest.txt -> MyTest.txt
ばんざーい!
または、次のコマンドを使用することで、すべての問題を回避できますgit mv
。
$ git mv Mytest.txt MyTest.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: Mytest.txt -> MyTest.txt