在历史Subversion修订版更改后修复git-svn存储库

时间:2015-01-15 12:48:41

标签: git svn git-svn svn-propset

我使用git-svn来保存共享Subversion存储库的克隆。最近有人在我git svn fetch修改了该版本之后编辑了修订版的提交消息( a la this SO question)。如何更正我的Git克隆以获得正确的提交消息?

我原本期望git svn reset后跟git 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. 我检查了除错误分支以外的分支。运行git svn reset没有任何区别:remotes/origin/branchname继续指向更近期的提交。不出所料,git svn fetch什么也没做。

  2. 我检查了remotes/origin/branchname并再次运行git svn reset。这很有效:remotes/origin/branchname指向了duff commit的父级。

  3. 我跑了git svn fetch。这绝对没有任何结果:没有提交任何提交,remotes/origin/branchname没有移动。

  4. 我在Subversion存储库中的那个分支上创建了几个虚拟提交(一个添加了一个空文件,下一个又删除了它),然后运行git svn fetch again

    这里真的很奇怪:duff提交没有被重新提起。相反,提取开始于我添加虚拟文件的提交,报告了"索引不匹配"在进程中。对添加了虚拟文件的提交运行git show,显示了我重置的提交和虚拟提交之间的所有差异。

    现在,运行git log --graph --decorate --pretty=oneline --abbrev-commit HEAD origin/branchname看起来像这样:

    * 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
    

    请注意,除了HEAD之外,现在没有任何内容指向此分支上的某些提交。

  5. 我很快得出结论,至少有一些这种行为只是git svn中的一个错误。当然,我在上面第4点看到的并不是应该发生的事情,至少是我的理解。

3 个答案:

答案 0 :(得分: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的数据被修复了。您仍然必须修复您当地的分支机构。例如,如果master跟踪SVN中继,请运行:

git rebase remotes/git-svn

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

git svn manpage的“reset”子命令一节中对此进行了很好的解释。

答案 1 :(得分: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时,这也会导致压缩提交

答案 2 :(得分:0)

如果遇到与我相同的问题,则可能是由于该帮助文档中有关更新branchs-maxrev的注释引起的。

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

“请注意,git-svn会跟踪出现分支或标签的最高修订版本。如果在提取后更改了分支或标签的子集,则必须手动编辑$ GIT_DIR / svn / .metadata以将其删除(或重置)分支-maxRev和/或标记-maxRev。”

在我的情况下,分支的历史记录已更改,并且重置不够聪明,无法跨分支重新设置其版本以重新捕获修订版本,而是使用了另一个分支的最高版本。