我手动移动了一个文件,然后对它进行了修改。根据 Git 的记录,这是一个新文件和一个被删除的文件。有没有办法强制 Git 把它视为文件移动操作?
我手动移动了一个文件,然后对它进行了修改。根据 Git 的记录,这是一个新文件和一个被删除的文件。有没有办法强制 Git 把它视为文件移动操作?
如果您的修改不是太严重,Git将自动检测到移动/重命名。只需git add
新文件,然后git rm
旧文件。然后,git status
将显示是否已检测到重命名。
此外,对于目录中的移动,您可能需要:
git add -A .
git status
以验证“new file”现在是“renamed”文件如果git status仍然显示“new file”而不是“renamed”,则需要遵循Hank Gay的建议分两个提交移动和修改。
git status
、git log
或git diff
时进行检测,而不是在您使用git add
、git mv
或git rm
时进行检测。进一步讲解重命名的检测,这只对已暂存的文件有意义。因此,对文件进行git mv
操作并对文件进行更改,可能会导致在git status
中将其视为重命名,但当您在文件上使用git stage
(与git add
相同)时,就会清楚地表明该更改过大,无法被检测为重命名。 - Jarl将移动和修改操作分别提交。
git diff
在一个提交中无法识别重命名操作,则它在两个提交中也无法识别。您需要使用-M
或--find-renames
选项来进行识别。所以,如果您提出这个问题的动机是为了在拉取请求中查看重命名操作(根据经验说),将其分成两个提交并不能更接近实现这个目标。 - mattliugit diff -M
或 git log -M
应该会自动检测到那些发生了小改动的重命名操作,只要它们确实是小改动。
如果你的小改动不是那么小,可以减少相似度阈值,例如:
$ git log -M20 -p --stat
将其从默认的50%降低到20%。
q
退出。别担心,在单独的 git log 视图中很难搞砸什么。 - theannouncerfoo
,现在改名为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 bar foo'操作,则只需确保在提交之前要执行git add foo
和git rm bar
。这可以通过单个git add -A
命令完成,或者可能需要使用git add foo; git commit -a
两个命令来完成。 - CB Baileyadd
该文件,git会将移动/修改拆分为删除/再添加。 - Michael Piefelgit commit
,那么这个过程就可以正常工作,否则就是错误的。此外,@CharlesBailey是正确的,你同样可以在第三步时使用普通的mv blah foo
命令,然后进行提交,得到相同的结果。 - DaFlame这完全是个感性的问题。Git通常相当擅长识别移动操作,因为GIt是一个内容追踪器。
所有这些只取决于你的“stat”如何显示它。唯一的区别在于-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 help log
-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可以“发现”这个新文件可能是先前被复制的。有时它做得很对,但有时它会找到完全不相关的文件,这些文件恰好具有相同的内容。 - Kent FredricFirst, cancel your staged add for the manually moved file:
$ git reset path/to/newfile $ mv path/to/newfile path/to/oldfile
Then, use Git to move the file:
$ git mv path/to/oldfile path/to/newfile
Of course, if you already committed the manual move, you may want to reset to the revision before the move instead, and then simply
git mv
from there.
git mv
,再进行编辑,然后让它生效,但我刚刚编辑了文件的 > 50%,并在一个提交中重命名/移动了它。换句话说,在执行 git mv
之前,你必须先编辑文件。 - undefinedgit mv oldfile newfile
命令,git status
会将更改注册为 modified: newfile
,但是在执行 git add newfile
后,状态会变为 deleted: oldfile
和 new file: newfile
。无论如何,这是正常的操作。 - undefinedgit add NEW && git rm OLD
来使Git识别移动操作的内容。add
+rm
的方法将把修改添加到索引中,这在某些情况下可能是不希望的(例如,在有实质性修改的情况下,Git可能不再认为它是一个文件重命名)。mv NEW OLD && git mv OLD NEW
。info=$(git ls-files -s -- "OLD" | cut -d' ' -f-2 | tr ' ' ,)
git update-index --add --cacheinfo "$info,NEW" &&
git rm --cached "$old"
~/.gitconfig
文件中:[alias]
mv-index = "!f() { \
old=\"$1\"; \
new=\"$2\"; \
info=$(git ls-files -s -- \"$old\" | cut -d' ' -f-2 | tr ' ' ,); \
git update-index --add --cacheinfo \"$info,$new\" && \
git rm --cached \"$old\"; \
}; f"
--cached
在git rm中一样。在我的情况下,我移动了整个目录,所以我使用了一个稍微不同的方法:git ls-files -s -- OLD |sed 's#\tOLD/#\tNEW/#'
,然后跟着使用git rm -r --cached OLD
。注意:sed中的\t
和尾随的/
匹配路径前面的制表符和目录分隔符,请使用从您的repo根目录开始的完整路径(这确保您仅匹配该目录,而不是任何类似命名的文件/目录)。 - Thomas Guyot-Sionnestmv-index
。 - undefined使用git mv
命令移动文件,而不是操作系统的移动命令:
https://git-scm.com/docs/git-mv
请注意,git mv
命令仅在Git版本1.8.5及以上才存在。因此,您可能需要更新您的Git以使用此命令。
old_file.txt
,执行git mv old_file.txt new_file.txt
等同于执行以下三个步骤:git rm --cached old_file.txt
、将old_file.txt
重命名为new_file.txt
、git add new_file.txt
。注意翻译时需保证内容原意不变且易于理解。 - Jarlgit mv
命令不会将它们添加到缓存中,但git add
会。我更喜欢将文件移回原处,这样就可以使用git mv
命令,然后使用git add -p
来查看我的修改集。 - dhardy