我在Git中有一个有点令人困惑的问题。 假设,我提交了一个文件dir1/ a .txt, git保存了一个提交历史

现在我需要将文件复制到dir2/A.txt(不是移动,而是复制)。 我知道有一个git mv命令,但我需要dir2/ a .txt具有与dir1/ a .txt相同的提交历史,并且dir1/ a .txt仍然保留在那里。

我不打算在创建副本后更新A.txt,所有未来的工作都将在dir2/A.txt上完成

我知道这听起来很混乱,我会补充说,这种情况是基于java的模块(mavenized项目),我们需要创建一个新版本的代码,以便我们的客户能够在运行时有2个不同的版本,第一个版本将最终在对齐时被删除。 当然,我们可以使用maven版本,我只是Git的新手,对Git在这里能提供什么很好奇。


当前回答

简单地复制文件,添加并提交:

cp dir1/A.txt dir2/A.txt
git add dir2/A.txt
git commit -m "Duplicated file from dir1/ to dir2/"

然后,下面的命令将显示完整的预拷贝历史记录:

git log --follow dir2/A.txt

要查看从原始文件继承的逐行注释,请使用以下命令:

git blame -C -C -C dir2/A.txt

Git不会在提交时跟踪副本,而是在检查历史记录时进行检测,例如Git blame和Git log。

大部分信息来自这里的答案:用Git记录文件复制操作

其他回答

与subversion不同,git没有每个文件的历史记录。如果查看提交数据结构,它只指向以前的提交和这次提交的新树对象。没有显式的信息存储在提交对象中,哪些文件被提交更改;也不知道这些变化的性质。

检查更改的工具可以基于启发式检测重命名。例如,git diff有选项-M,打开重命名检测。因此,在重命名的情况下,git diff可能会告诉你一个文件被删除了,另一个文件被创建了,而git diff -M实际上会检测到移动并相应地显示更改(详情请参见man git diff)。

所以在git中,这不是你如何提交你的更改的问题,而是你以后如何查看所提交的更改。

为了完整起见,我想补充一点,如果你想复制一个充满受控和不受控文件的整个目录,你可以使用以下方法:

git mv old new
git checkout HEAD old

不受控制的文件将被复制,所以你应该清理它们:

git clean -fdx new

我在这里稍微修改了Peter的回答,创建了一个可重用的、非交互式的shell脚本git-split.sh:

#!/bin/sh

if [[ $# -ne 2 ]] ; then
  echo "Usage: git-split.sh original copy"
  exit 0
fi

git mv "$1" "$2"
git commit -n -m "Split history $1 to $2 - rename file to target-name"
REV=`git rev-parse HEAD`
git reset --hard HEAD^
git mv "$1" temp
git commit -n -m "Split history $1 to $2 - rename source-file to temp"
git merge $REV
git commit -a -n -m "Split history $1 to $2 - resolve conflict and keep both files"
git mv temp "$1"
git commit -n -m "Split history $1 to $2 - restore name of source-file"

在我的例子中,我在我的硬盘驱动器上进行了更改(从我的工作副本中的一个路径剪切/粘贴大约200个文件夹/文件到我的工作副本中的另一个路径),并使用SourceTree(2.0.20.1)来执行检测到的更改(一个添加,一个删除),只要我同时执行添加和删除,它就会自动合并为带有粉红色R图标的单个更改(我假设是重命名)。

我确实注意到,因为我一次有这么多更改,SourceTree检测所有更改的速度有点慢,所以我的一些阶段性文件看起来只是添加(绿色加)或删除(红色减),但我不断刷新文件状态,并在最终出现新的更改时持续呈现,几分钟后,整个列表完美无缺,可以提交了。

我验证了历史记录是存在的,只要当我寻找历史记录时,我检查了“跟踪重命名文件”选项。

简单地复制文件,添加并提交:

cp dir1/A.txt dir2/A.txt
git add dir2/A.txt
git commit -m "Duplicated file from dir1/ to dir2/"

然后,下面的命令将显示完整的预拷贝历史记录:

git log --follow dir2/A.txt

要查看从原始文件继承的逐行注释,请使用以下命令:

git blame -C -C -C dir2/A.txt

Git不会在提交时跟踪副本,而是在检查历史记录时进行检测,例如Git blame和Git log。

大部分信息来自这里的答案:用Git记录文件复制操作