我手动移动了一个文件,然后我对其进行了修改。根据Git,它是一个新文件和一个删除文件。有没有办法强迫Git将其视为文件移动?
答案 0 :(得分:364)
如果您的修改不是太严重,Git会自动检测移动/重命名。只需git add
新文件,git rm
旧文件。然后git status
会显示是否检测到重命名。
另外,对于目录周围的移动,您可能需要:
git add -A .
git status
以验证“新文件”现在是“重命名”文件如果git状态仍然显示“新文件”而不是“重命名”,则需要遵循Hank Gay’s建议,并在两次单独的提交中进行移动和修改。
答案 1 :(得分:87)
在单独的提交中执行移动和修改。
答案 2 :(得分:43)
这都是一种感性的东西。 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.
答案 3 :(得分:29)
git diff -M
或git log -M
应自动将此类更改检测为重命名并进行微小更改,只要确实如此。
如果您的次要更改不是次要的,您可以减少相似性threashold,例如
$ git log -M20 -p --stat
将其从默认的50%降低到20%。
答案 4 :(得分:27)
这是一个快速而又脏的解决方案,适用于未提交的一个或几个重命名和修改过的文件。
假设该文件名为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.
答案 5 :(得分:17)
如果您说的是git status
没有显示重命名,请尝试使用git commit --dry-run -a
答案 6 :(得分:10)
如果你正在使用TortoiseGit,重要的是要注意Git的自动重命名检测在提交期间发生,但事实上这种情况并不总是事先由软件显示。我已将两个文件移动到另一个目录并执行了一些轻微的编辑。我使用TortoiseGit作为我的提交工具,更改制作列表显示文件被删除和添加,而不是移动。从命令行运行git status显示了类似的情况。但是在提交文件后,它们显示为在日志中重命名。所以你的问题的答案是,只要你没有做过任何过于激烈的事情,Git就应该自动获取重命名。
编辑:显然,如果您添加新文件然后从命令行执行git状态,则重命名应该在提交之前显示。
编辑2:此外,在TortoiseGit中,在提交对话框中添加新文件但不提交它们。然后,如果您进入Show Log命令并查看工作目录,您将看到Git在提交之前是否检测到重命名。
这里提出了同样的问题:https://tortoisegit.org/issue/1389并且已经记录为在此处修复的错误:https://tortoisegit.org/issue/1440事实证明这是TortoiseGit的提交对话框的显示问题,并且还存在于git状态如果你还没有添加新文件。
答案 7 :(得分:3)
使用git mv
命令移动文件,而不是OS移动命令:
https://git-scm.com/docs/git-mv
请注意,{{1}}命令仅存在于Git 1.8.5及更高版本中。所以你可能需要更新你的Git才能使用这个命令。
答案 8 :(得分:3)
或者你可以通过here尝试这个问题Amber的答案! 再次引用它:
首先,取消手动移动文件的暂存添加:
$ git reset path/to/newfile
$ mv path/to/newfile path/to/oldfile
然后,使用Git移动文件:
$ git mv path/to/oldfile path/to/newfile
当然,如果您已经提交了手动移动,您可能希望在移动之前重置为修订版,然后从那里简单地git mv。
答案 9 :(得分:2)
最近,当移动(但没有修改)某些文件时,我遇到了这个问题。
问题是当我移动文件时Git改变了一些行结尾,然后无法判断文件是否相同。
使用git mv
解决了问题,但它只适用于单个文件/目录,并且我在存储库的根目录中有很多文件要做。
解决这个问题的一种方法是使用一些bash / batch魔法。
另一种方式是以下
git commit
。这会更新行结尾。git commit --amend
git commit --amend
。这次线路结尾没有变化,所以Git很高兴答案 10 :(得分:1)
对我来说,它可以在提交之前保存所有更改并再次弹出它们。这使得git重新分析添加/删除的文件,并正确地将它们标记为已移动。
答案 11 :(得分:0)
有一个更好的“命令行”方法可以做到这一点,我知道这是一个黑客,但我从来没有找到一个好的解决方案。
使用TortoiseGIT:如果你有一个GIT提交,其中某些文件移动操作显示为加载/删除的加载而不是重命名,即使文件只有很小的更改,那么执行以下操作:
新提交现在将正确显示文件重命名...这将有助于维护正确的文件历史记录。
答案 12 :(得分:0)
当我同时编辑,重命名和移动文件时,这些解决方案都不起作用。解决方案是在两次提交(编辑和重命名/移动单独)中进行,然后fixup
通过git rebase -i
进行第二次提交,以便在一次提交中进行。
答案 13 :(得分:0)
我对这个问题的理解是“如何让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
答案 14 :(得分:0)
其他答案已经涵盖了,您可以简单地git 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"