我手动移动了文件,然后对其进行了修改。根据Git的说法,它是一个新文件,并且已删除文件。有什么方法可以迫使Git将其视为文件移动?
git mv
则不会将它们添加到缓存中git add
。我更喜欢将文件移回以便可以使用git mv
,然后git add -p
查看我的更改集。
我手动移动了文件,然后对其进行了修改。根据Git的说法,它是一个新文件,并且已删除文件。有什么方法可以迫使Git将其视为文件移动?
git mv
则不会将它们添加到缓存中git add
。我更喜欢将文件移回以便可以使用git mv
,然后git add -p
查看我的更改集。
Answers:
如果您的修改不太严格,Git将自动检测到移动/重命名。只是git add
新文件和git rm
旧文件。git status
然后将显示它是否检测到重命名。
此外,对于目录移动,您可能需要:
git add -A .
git status
以验证“新文件”现在是“重命名”文件如果git status仍然显示“新文件”而不是“重命名”,则需要遵循Hank Gay的建议,并在两次单独的提交中进行移动和修改。
git status
,git log
或者git diff
,不是在你这样做的时候git add
,git mv
或git rm
。进一步讲,检测重命名仅对暂存文件有意义。因此git mv
,在文件中进行更改之后,git status
就好像将其视为一样rename
,但是当您在文件上使用git stage
(与相同git add
)时,很明显该更改太大而无法检测为重命名。
git add
,正如@ jrhorn424建议的那样,可能应该一次将整个存储库添加进去。
在单独的提交中进行移动和修改。
git diff
在一次提交中无法识别重命名,则在两次提交中将无法识别重命名。您将需要使用-M
aka --find-renames
来做到这一点。因此,如果导致您提出此问题的动机是在请求请求中看到重命名(从经验上来讲),将其分为两个提交将不会进一步实现该目标。
都是感性的东西。Git通常很擅长识别动作,因为GIT是内容跟踪器
真正取决于您的“状态”如何显示它。唯一的区别是-M标志。
git log --stat -M
commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date: Fri Jan 9 22:13:51 2009 +1300
Category Restructure
lib/Gentoo/Repository.pm | 10 +++++-----
lib/Gentoo/{ => Repository}/Base.pm | 2 +-
lib/Gentoo/{ => Repository}/Category.pm | 12 ++++++------
lib/Gentoo/{ => Repository}/Package.pm | 10 +++++-----
lib/Gentoo/{ => Repository}/Types.pm | 10 +++++-----
5 files changed, 22 insertions(+), 22 deletions(-)
git log --stat
commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date: Fri Jan 9 22:13:51 2009 +1300
Category Restructure
lib/Gentoo/Base.pm | 36 ------------------------
lib/Gentoo/Category.pm | 51 ----------------------------------
lib/Gentoo/Package.pm | 41 ---------------------------
lib/Gentoo/Repository.pm | 10 +++---
lib/Gentoo/Repository/Base.pm | 36 ++++++++++++++++++++++++
lib/Gentoo/Repository/Category.pm | 51 ++++++++++++++++++++++++++++++++++
lib/Gentoo/Repository/Package.pm | 41 +++++++++++++++++++++++++++
lib/Gentoo/Repository/Types.pm | 55 +++++++++++++++++++++++++++++++++++++
lib/Gentoo/Types.pm | 55 -------------------------------------
9 files changed, 188 insertions(+), 188 deletions(-)
git帮助日志
-M
Detect renames.
-C
Detect copies as well as renames. See also --find-copies-harder.
git log -M1 -C1 -B1 -D --find-copies-harder
git可以“发现”新文件可能已被首先复制。有时,它会执行正确的操作,而有时,它会发现恰好具有相同内容的完全不相关的文件。
git diff -M
或git log -M
应自动将此类更改检测为重命名,只要确实存在,即可进行较小的更改。如果您的次要更改不是次要更改,则可以降低相似性阈值,例如
$ git log -M20 -p --stat
将其从默认的50%减少到20%。
对于一个或几个未提交的重命名和修改的文件,这是一个快速而肮脏的解决方案。
假设文件已命名foo
,现在命名为bar
:
重命名bar
为临时名称:
mv bar side
结帐foo
:
git checkout HEAD foo
用Git 重命名foo
为bar
:
git mv foo bar
现在,将您的临时文件重命名为bar
。
mv side bar
最后一步是将更改后的内容重新存储到文件中的步骤。
尽管这可以解决问题,但是如果所移动的文件与原始git的内容差异太大,则将其确定为新对象会更有效。让我示范一下:
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: work.js
$ git add README.md work.js # why are the changes unstaged, let's add them.
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
deleted: README
new file: README.md
modified: work.js
$ git stash # what? let's go back a bit
Saved working directory and index state WIP on dir: f7a8685 update
HEAD is now at f7a8685 update
$ git status
On branch workit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.idea/
nothing added to commit but untracked files present (use "git add" to track)
$ git stash pop
Removing README
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
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: README
modified: work.js
Dropped refs/stash@{0} (1ebca3b02e454a400b9fb834ed473c912a00cd2f)
$ git add work.js
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
modified: work.js
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: README
$ git add README # hang on, I want it removed
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
deleted: README
new file: README.md
modified: work.js
$ mv README.md Rmd # Still? Try the answer I found.
$ git checkout README
error: pathspec 'README' did not match any file(s) known to git.
$ git checkout HEAD README # Ok the answer needed fixing.
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
modified: work.js
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: README.md
modified: work.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
Rmd
$ git mv README README.md
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
modified: work.js
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: work.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
Rmd
$ mv Rmd README.md
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
modified: work.js
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: work.js
$ # actually that's half of what I wanted; \
# and the js being modified twice? Git prefers it in this case.
git mv
只是对git rm
/ 的方便git add
。如果你已经做了“MV酒吧富”,那么所有你需要做的是确保你已经git add foo
和git rm bar
在提交前。这可以作为单个git add -A
命令完成,也可以按git add foo; git commit -a
顺序完成。
add
再次文件,git的休息移动/修改成删除/再次添加。
git commit
在执行第3步之后,此过程将起作用,否则不正确。另外,@ CharlesBailey是正确的,您可以轻松地mv blah foo
在第3步中执行常规操作,然后提交,并获得相同的结果。
如果您使用的是TortoiseGit,请务必注意,Git的自动重命名检测是在提交过程中发生的,但是这种情况不会始终由软件预先显示。我已经将两个文件移到了另一个目录,并进行了一些轻微的编辑。我使用TortoiseGit作为提交工具,“所做的更改”列表显示正在删除和添加而不是移动的文件。从命令行运行git status显示了类似的情况。但是,提交文件后,它们在日志中显示为已重命名。因此,您的问题的答案是,只要您还没有做任何太过激烈的事情,Git就会自动选择重命名。
编辑:显然,如果您添加新文件,然后从命令行执行git status,则在提交之前应显示重命名。
编辑2:此外,在TortoiseGit中,在提交对话框中添加新文件,但不要提交它们。然后,如果进入Show Log命令并查看工作目录,则会看到Git在提交之前是否已检测到重命名。
此处提出了相同的问题:https : //tortoisegit.org/issue/1389并已记录为要在此处修复的错误:https : //tortoisegit.org/issue/1440 原来这是TortoiseGit提交的显示问题对话框,如果您尚未添加新文件,则还处于git状态。
使用git mv
命令移动文件,而不是操作系统移动命令:https :
//git-scm.com/docs/git-mv
请注意,该git mv
命令仅存在于Git 1.8.5及更高版本中。因此,您可能必须更新Git才能使用此命令。
我理解这个问题的方式是“如何使git识别旧文件的删除并在文件移动时创建新文件”。
删除旧文件并插入旧文件后,在工作目录中是,git status
将显示“ deleted: old_file
”和“ Untracked files: ... new_file
”
但是在暂存索引/级别中,一旦您使用git添加和删除文件,它将被识别为文件移动。为此,假设您已经使用操作系统完成了删除和创建,请提供以下命令:
git add new_file
git rm old_file
如果文件的内容相似度超过50%,则运行git status
命令应为您提供:
renamed: old_file -> new_file
git status
会说“ deleted: old_file
”和“ Untracked files: ... new_file
”:从Git 2.18开始不存在:stackoverflow.com/a/50573107/6309
old_file.txt
,那么git mv old_file.txt new_file.txt
就相当于git rm --cached old_file.txt
,mv old_file.txt new_file.txt
,git add new_file.txt
。