Repairing git-svn repository after historical Subversion revision changed
Asked Answered
G

3

8

I use git-svn to keep a clone of a shared Subversion repository. Recently someone edited the commit message of a revision (a la this SO question) after I had git svn fetched that revision. How can I correct my Git clone to have the correct commit message?

I had expected git svn reset followed by git svn fetch to refetch this commit and update things, leaving me to only need to fix up my local branches, but that doesn't actually seem to do anything; the git svn fetch doesn't refetch the commits I reset to.

(Yes I think changing the commit message was a bad idea, but that's not something I have control over.)

Update: I tried the process that sleske suggested (in fact, I'd tried it before asking the question, but I just tried again just in case), but with no luck. I get output like the below:

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
$ 

There's no output from git svn fetch (or there is if there has been commits since I last ran it, but it's just fetching the new commits, not refetching the old ones), and in particular there's no rereading message as in sleske's example.

In case it's relevant, I'm using Git v2.0.4.

Update 2: Slightly redacted .git/config below:

[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/*

I'll not post the full output of git branch -avv, because there's a lot of it, but that's where it gets really interesting, so I'll post a list of everything I did:

  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.

I'm rapidly coming to the conclusion that at least some of this behaviour is simply a bug in git svn. Certainly what I saw in point 4 above is not something that should happen at all, at least by my understanding.

Giesser answered 15/1, 2015 at 12:48 Comment(3)
Could you post: a) the contents of ".git/config" (where the git-svn remote is configured), and b) the output of git branch -avv before and after the invocation of git svn reset .... The latter should show what happens to the remote-tracking branch used by git svn.Bide
@Bide I've added the .git/config as requested, and done a bit of digging based on the output of git branch -avv. It's very odd.Giesser
Yes, very odd, and quite likely a bug in git svn. I'm afraid that in order to get more help, you'll have to provide a reproducible test case. You could try whipping up a script that creates a local SVN repo , then checks it out via git svn. If you use the same repo layout and options, and create structurally similar commits, maybe you can reproduce the problem.Bide
H
3

git svn reset <revision-number> works, but you have to specify a revision number that is earlier than the offending commit, and then re-do git svn fetch. Let's say the changed commit is R.100, you'll need to git svn reset 99 then do git svn fetch, only that will re-fetch the new changed commit.

As of your case of 730c2ab containing squashed of b89af06 to 93920f9:

 * 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 occasionally do that on commits that has changed. I am not sure of the specifics, but I encountered occasionally when the working copy of a particular commit on the svn has changed since the last fetch, git svn will squash the changes together with the next commit on the next fetch. To solve this problem, you can reset to the previous commit, and re-fetch again

EDIT:

I didn't notice previously that ce51022 is already detached from your main branch. SVN does branching differently and git-svn will not be able to persist your git branches on svn. This will also result in squashed commit too when you do git svn dcommit or git svn fetch/rebase

Hodgson answered 4/1, 2018 at 2:3 Comment(0)
B
2

git svn reset is indeed the right way to do it. Assuming SVN revision 4711 was changed, the steps are:

1) Discard the changed SVN revision (and everything after it):

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

2) Fetch the changed revision:

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

3) Now git-svn's data is repaired. You must still repair your local branches. For example, if master tracks the SVN trunk, run:

git rebase remotes/git-svn

(where "remotes/git-svn" is the remote-tracking branch created by git svn - it may have a different name).

This is explained quite well in the git svn manpage, in the section on the "reset" subcommand.

Bide answered 16/1, 2015 at 15:0 Comment(1)
This is exactly what I tried originally, but the git svn fetch doesn't do any rereading steps. I've updated the original question with the full output I'm seeing.Giesser
P
0

If you ran in to the same problem as me, it may be caused by the note on this help document about updating branches-maxrev.

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

"Note that git-svn keeps track of the highest revision in which a branch or tag has appeared. If the subset of branches or tags is changed after fetching, then $GIT_DIR/svn/.metadata must be manually edited to remove (or reset) branches-maxRev and/or tags-maxRev as appropriate."

In my case, the branch history had changed and reset wasn't smart enough to set it back across branches to have revisions re-captured, but instead was using the highest rev of another branch.

Pendentive answered 16/4, 2019 at 12:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.