使用 git-svn 移动/重命名目录



我的公司使用SVN存储库,但我想使用Git。目前我正在使用 git-svn,但是当我移动或重命名包含 Git 中多个文件的目录并"git svn dcommit"进行此类更改时,在 SVN 存储库中,这会导致单个文件移动:

Changed paths:
D /directory/file1
D /directory/file2
D /directory/file3
D /directory/file4
...
A /renamedDirectory
A /renamedDirectory/file1 (from /directory/file1:67918)
A /renamedDirectory/file2 (from /directory/file2:67918)
A /renamedDirectory/file3 (from /directory/file3:67918)
A /renamedDirectory/file4 (from /directory/file4:67918)
....

相反,我希望看到这样的东西:

Changed paths:
D /directory
A /renamedDirectory (from /directory:67918)

即完整目录重命名。有什么办法可以解决这个问题吗?

在 git 中重命名(移动)目录时,git 移动的只是文件,而不是目录。

如果我将名为pdfs的文件夹重命名为pdfs2

$ git mv pdfs pdfs2
$ git status
renamed:    pdfs/filea -> pdfs2/filea
renamed:    pdfs/fileb -> pdfs2/fileb

所以我认为这就是 git 的工作方式,所以 git-svn 也是这样工作的。

git 没有办法说"我 100% 确定这是一个完整的目录移动操作",因此将其转换为 SVN 作为目录移动。Git 只知道/关心文件。


另外:你会注意到,如果你尝试提交一个空目录,git 会抱怨:

$ mkdir afolder
$ git add afolder && git commit -m "Added afolder"
On branch master
nothing to commit, working tree clean

这又是因为 git 不关心目录,只关心文件。

在文件移动和复制方面,SVN 和 Git 之间有一个主要区别:

  • Subversion 保留在仓库中执行的每个复制操作的复制自元数据。

  • Git 不保留这种元数据,而是依靠某些启发式方法来确定文件或目录是被复制还是移动。

不同的 Git 命令使用不同的重命名检测技术,例如git log --stat -M确实会检测目录重命名:

git log --stat -M
...
{directory => renamedDirectory}/file1 
{directory => renamedDirectory}/file2
{directory => renamedDirectory}/file3
{directory => renamedDirectory}/file4

但是,git-svn在将 Git 提交发送到 SVN 存储库时不会尝试检测重命名的目录,因此,git-svn生成的复制元数据不会反映您所期望的目录重命名,而是重命名相应修订版中的单个文件。

我们在SubGit中采用了不同的方法,这是git-svn的替代方案:当一个人使用Git移动目录时:

$ git mv directory renamedDirectory

然后将此更改推送到启用 SubGit 的 Git 存储库:

$ git commit -m 'Rename directory to renamedDirectory'
$ git push

SubGit 确实将此更改转换为 Subversion 存储库中的目录重命名:

Changed paths:
D /directory
A /renamedDirectory (from /directory:123)

如果你发现在 Subversion 仓库中保留这种元数据很重要,你可以考虑尝试 SubGit。这是一个快速入门指南。

最新更新