修复历史 Subversion 版本更改后的 git-svn 仓库

8
我使用git-svn来维护共享Subversion存储库的克隆。最近,有人在我执行了git svn fetch命令后编辑了一个版本的提交信息(就像这个SO问题中所述)。那么,我该如何更正我的Git克隆以拥有正确的提交消息?
我原本期望通过git svn resetgit svn fetch来重新获取此提交并更新内容,从而只需要修复我的本地分支即可。但实际上它似乎并没有做任何事情;git svn fetch未重新获取我重置的提交。
(是的,我认为更改提交消息是不明智的,但我无法控制。)
更新:我尝试了sleske建议的过程(实际上,在提问之前我已经尝试过,但我刚刚再次尝试了一下),但没有成功。我得到的输出如下:
me_and@centos ~/code ((358a2dd...)) Fri 16 Jan 15:31:27
$ git svn reset -p 55102
r55094 = 25d126219f7eeddfc7d0842704c7efcc0443dd70     (refs/remotes/origin/branchname)

me_and@centos ~/code ((358a2dd...)) Fri 16 Jan 15:33:06
$ git svn fetch

me_and@centos ~/code ((358a2dd...)) Fri 16 Jan 15:33:08
$ 

git svn fetch命令没有输出(或者只有在我上次运行它之后进行了提交,但是它只是获取新的提交,而不是重新获取旧的提交),特别地,没有像sleske示例中的rereading消息。

如果相关的话,我正在使用Git v2.0.4。

更新2:下面是略加删减的.git/config

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[svn-remote "svn"]
    url = http://server/repos/repo
    fetch = trunk:refs/remotes/origin/trunk
    branches = branches/*:refs/remotes/origin/*
    tags = tags/v10/*:refs/remotes/origin/tags/*
    tags = tags/v11/*:refs/remotes/origin/tags/*
    tags = tags/v12/*:refs/remotes/origin/tags/*
    tags = tags/v13/*:refs/remotes/origin/tags/*

我不会发布完整的git branch -avv输出,因为它非常冗长。但这是最有趣的部分,所以我将列出我所做的一切:

  1. I had a checkout of a branch other than the branch with the error. Running git svn reset made no difference: remotes/origin/branchname continued to point at a more recent commit. Unsurprisingly, git svn fetch did nothing.

  2. I checked out remotes/origin/branchname and ran git svn reset again. This worked: remotes/origin/branchname pointed at the parent of the duff commit.

  3. I ran git svn fetch. This did absolutely nothing: no commits were fetched and remotes/origin/branchname didn't move.

  4. I created a couple of dummy commits on that branch in the Subversion repository (one added an empty file, the next deleted it again), then ran git svn fetch again.

    Here's where it gets really odd: the duff commit wasn't refetched. Instead, the fetch started at the commit where I added the dummy file, reported an "Index mismatch" in the process.Running git show on the commit that added the dummy file shows it with all the diffs between the commit I reset to and the dummy commit.

    Now, running git log --graph --decorate --pretty=oneline --abbrev-commit HEAD origin/branchname looks like this:

    * 7b12bbc (origin/branchname) Remove dummy file
    * 730c2ab Add dummy file  # But `git show 730c2ab` includes the diffs between b89af06 and 93920f9 as well
    | * 93920f9 (HEAD) Uninteresting commit
    | * 91c7163 Uninteresting commit
    | * ce51022 Commit with the changed commit message
    |/
    * b89af06 Uninteresting commit
    

    Note that, other than HEAD, there is now nothing pointing to some of the commits on this branch.

我越来越认为,至少其中一些行为只是git svn中的一个bug。毫无疑问,我在上面第4点看到的情况根本不应该发生,至少按照我的理解是这样。


请提供以下内容:a)“.git/config”文件的内容(其中配置了git-svn远程),以及b)在调用“git svn reset…”之前和之后的“git branch -avv”的输出。后者应该显示“git svn”使用的远程跟踪分支发生了什么变化。 - sleske
@sleske,我已经按要求添加了.git/config文件,并根据git branch -avv的输出做了一些调查。这非常奇怪。 - me_and
1
是的,非常奇怪,很可能是git svn中的一个错误。恐怕为了获得更多帮助,您需要提供可重现的测试用例。您可以尝试编写一个脚本,创建一个本地SVN存储库,然后通过git svn检出它。如果您使用相同的存储库布局和选项,并创建结构相似的提交,则可能可以重现该问题。 - sleske
3个回答

2

git svn reset 是正确的操作。假设 SVN 版本 4711 发生了改变,以下是需要执行的步骤:

1)放弃已改变的 SVN 版本(以及它后面的所有版本):

$ git svn reset -p 4711
r1 = 18614es3df44c30da07 (refs/remotes/git-svn)

2) 获取已更改的版本:

$ git svn fetch
rereading 18614es3df44c30da07 
        A       trunk/a
r4711 = 8dfb7d0758dbbc1d06004 (refs/remotes/git-svn)
        A       trunk/b
r4712 = e7337af3743e48c90ef3fa09906378b95997314c (refs/remotes/git-svn)
[...]

3)现在git-svn的数据已经修复,但你仍需要修复本地分支。例如,如果主分支跟踪SVN主干,请运行:

git rebase remotes/git-svn

(其中"remotes/git-svn"是git svn创建的远程跟踪分支,它可能有不同的名称)。

在"reset"子命令的章节中,这个问题在git svn手册中解释得很清楚。


1
这正是我最初尝试的方法,但是 git svn fetch 没有执行任何 rereading 步骤。我已经更新了原始问题,并附上了完整的输出。 - me_and

2

git svn reset <revision-number> 可以解决问题,但您需要指定一个早于有问题的提交的修订号,然后重新执行 git svn fetch。假设更改的提交是 R.100,您需要执行 git svn reset 99 然后执行 git svn fetch,这样才能重新获取新更改的提交。

对于您的情况,730c2ab 包含了从 b89af0693920f9 的压缩:

 * 7b12bbc (origin/branchname) Remove dummy file
 * 730c2ab Add dummy file  # But `git show 730c2ab` includes the diffs 
     between b89af06 and 93920f9 as well
 | * 93920f9 (HEAD) Uninteresting commit
 | * 91c7163 Uninteresting commit
 | * ce51022 Commit with the changed commit message
 |/
 * b89af06 Uninteresting commit

git-svn有时会在更改提交时发生这种情况。我不确定具体情况,但是我遇到过这种情况:当svn上特定提交的工作副本自上次获取以来发生更改时,git svn将把更改与下一次获取时的下一个提交合并。要解决此问题,您可以重置到上一个提交,然后重新获取。

编辑:

我之前没有注意到ce51022已经从您的主分支中分离出来。SVN使用不同的分支方式,因此git-svn无法在svn上保留您的git分支。这也会导致在执行git svn dcommit或git svn fetch/rebase时压缩提交。


0
如果你遇到了和我一样的问题,可能是由于更新branches-maxrev时帮助文档上的注释所导致的。

https://git-scm.com/docs/git-svn

请注意,git-svn会跟踪分支或标签出现的最高版本。如果在获取后更改了分支或标签的子集,则必须手动编辑$GIT_DIR/svn/.metadata以适当地删除(或重置)branches-maxRev和/或tags-maxRev。
在我的情况下,分支历史已更改,重置不足以将其设置回跨分支重新捕获修订版,而是使用另一个分支的最高版本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接