Question

I'm using git version 1.8.5.3 from the Arch Linux repository at home, and git version 1.8.1.2 from Ubuntu 13.10 at work. At work, we're use svn, so I deal with it using git svn.

I checked out the svn repository using git svn, at work and at home. The commit messages containing the git-svn-id are the same. Same goes for the author and the date. However, the resulting commit hash is not the same.

git svn fetch && git svn rebase 

works fine. However, if I try to merge some commits I made on one of the repositories via git between the two, git naturally fails to detect parents and spits out merge errors.

I'm thinking, this can only be due to changes in hash calculations. This would also break other git repositories so probably this is a problem connected to git svn.

first edit

git log --pretty=raw

shows different parents for all commits. That explains the different hashes but how did this happen in the first place? Turns out, that if I go all the way back to the first commits, they indeed have the same parents and thus the correct hashes. So somewhere along the way, something must have changed...

second edit

Found the last common commit hash using

git merge-base branch1 branch2

The commit following is a svn merge branch. Is this expected behavior?

third edit

What does work is to use

git cherry-pick hash

and apply the commits one by one...

update

All my fault. I checked out the entire svn repo at work but only the trunk at home. That's why the commit hashes were different starting from a merge of two svn branches.

Was it helpful?

Solution

I know the situation, working with an SVN repository myself via git-svn with some co-workers.

You basically have two options:

The easy way is to ONLY share code via SVN. This is the easy solution, because you'd use Git only as a sophisticates SVN-client with powerful local abilities. The only word of warning here is: NEVER EVER EVER EVER rebase a commit that already went into SVN! Or use a rebase-equivalent operation. Git-svn uses git-rebase internally to sync the changes that went into SVN without your local copy noticing and has to reorder your local commits.

If you decide that it is a good idea to also share code via Git, without involving SVN, things get way more complicated.

First of all, you should start with cloning a repository from SVN. This repository should be the master for everyone, and it should contain both the remote SVN branches, as well as local tracking branches for every branch in SVN that you might need. You'd be able to create them later as well, if you need them.

To get the repository to a new machine, copy the whole repo directory, including the .git directory, to the new machine.

To share code, create a remote Git repo somewhere and add this as a new remote in every local repo. You can then push.

Be careful NOT to push the branches that track SVN! Your world of code sharing now is separated into two kind of branches: Either the branch is Git-only. Then you can push it to any other Git repo you want. OR the branch is tracking an SVN branch. Then you MUST NOT push it anywhere for sharing code.

With Git-only branches, the usual rules for Git apply: Be careful when rebasing anything that got pushed (i.e. don't rebase!).

With SVN branches, things are different. My own workflow is like this:

git checkout master
git add stuff 
git commit 
git push                  // regular GIT workflow until here...
git checkout svntrunk     // name of the local branch tracking SVN trunk
git svn fetch             // get all updates from SVN in any branch
git svn rebase            // update trunk in local svntrunk tracking branch
git merge master --no-ff  // merge local master to SVN - fast-forward is not allowed
                          // because SVN has no way of be alike - your changes have
                          // to be a regular commit in the SVN branch
git svn dcommit           // move that commit into SVN repo
git svn tag v0.0.1-alpha  // optional, but tagging in SVN only works after dcommit
git checkout master       // back to work

Updating a branch that is related to an SVN branch uses rebase operations. So applying the usual Git rules about pushing a rebased branch, it becomes clear that this will not work! So don't push SVN tracking branches. Don't pull them. Only have them local and update them from SVN.

This two-branch workflow is not very nice. It allows you to share code via Git with your co-workers, but it doubles every branch that has to be in the SVN repository. And depending on how many people do the merging, the svn tracking branches will contain many commits that are actually their merge commits, but your local Git repo will not recognize them as merges. So the SVN branch in your local Git repo only knows about YOUR merges.

The situation will get worse if some of your co-workers use SVN directly, without Git. That way, you'd also have to merge back the changes in svntrunk to master. I have no experience with this, but I would say that in this situation it is best to avoid sharing code via Git, and remain in the single git-svn repo situation. Otherwise it will get VERY messy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top