1

I have a somewhat convoluted setup (as in git svn dcommit committing wrong file?) that looks something like this (produced in Dia, testrepo.dia, posted in this gist) - and is simulated with the script below, testrepo.sh:

/tmp/testrepo.png

Basically, I've had an SVN repository on a web server (myrepo_svn_WS), which at first I worked with through an SVN working copy on my local PC (myrepo_svnco). After a while, I stopped with that, and I moved to git-svn; but instead of using it directly from my local PC - I had set up a myrepo_gitsvn on my local server; from it a bare git repo is made on the local server, myrepo_git_LS.git, which is added as a remote origin of the myrepo_gitsvn. The idea is then that I can work from local PCs in respect to myrepo_git_LS.git, and keep the local network work in sync - even if the svn web server goes temporarily offline.

The below script, testrepo.sh, simulates this process locally - including the myrepo_svn_WS going offline. If you use the script as is, you'll notice that the system can "recover" from the SVN "WS" server going offline, and the log in that case is testrepo_nofail.log. However, if you uncomment the #~ commented lines, which do a git fetch origingit, you will notice that the process fails, for which the log is testrepo_fail.log:

remote: Using index info to reconstruct a base tree...
remote: Falling back to patching base and 3-way merge...
remote: Auto-merging folder/file.txt
remote: CONFLICT (content): Merge conflict in folder/file.txt
remote: Failed to merge in the changes.
remote: Patch failed at 0001 5th git commit
remote: 
remote: When you have resolved this problem run "git rebase --continue".
remote: If you would prefer to skip this patch, instead run "git rebase --skip".
remote: To check out the original branch and stop rebasing run "git rebase --abort".

What confuses me here (and why I find this unexpected) - is that I am the only user here, and thus I don't even use branches at all! In that case, how could I possibly get a "merge conflict"?

The thing is - now the system has actually ended up in this failed state; so my question is: how can I recover the system back to proper working state, such that when I do a commit and push from the local myrepo_git_wc, the SVN web sever myrepo_svn_WS properly updates?

A few notes from comparing the logs with meld:

Note that right after the "Simulating merge conflict via git fetch" part, the process seems to go on properly - except that there is now a origingit/master branch (click for full size):

testrepo_meld_01.png

I didn't think much of this, because I didn't think of git-svn as a branch; but here is a subquestion: of git-svn and origingit/master, which one is a branch?

That part ends here:

/testrepo_meld_02.png

Notice that in the end, the non-failed process shows the log graph tree as "compacted" or "flattened" (i.e. no branches are sticking out) - while the failed process at that point doesn't complain of errors, but shows the log graph tree as branched.

The problem occurs only after the '6th git commit':

testrepo_meld_03.png

The failed process actually starts, for some reason 'Applying 5th git commit', which at that point should have already been handled; and at that point, the merge conflict occurs.

So, provided my system (or rather, myrepo_gitsvn) is in this failed state, what can I do to recover it?

Here is the testrepo.sh code:

set -x

rm -rf /tmp/myrepo*
cd /tmp

echo "simulating svn web server repo"

svnadmin create myrepo_svn_WS
# svn co file:///tmp/myrepo_svn_WS myrepo_svnco
read -s -p "Enter ssh pass [note, you will be prompted again via GUI for the same]: " SSHPASS
export SSHPASS
# note: the next command will again prompt for sshpass in GUI once, regardless of the SSHPASS variable
sshpass -e svn co svn+ssh://localhost/tmp/myrepo_svn_WS myrepo_svnco
cd /tmp/myrepo_svnco

echo "Adding first commits via svn"

echo aaa > AA.txt
svn add AA.txt
sshpass -e svn ci -m 'first svn commit'

echo bbb > BB.txt
svn add BB.txt
sshpass -e svn ci -m '2nd svn commit'

echo ccc > CC.txt
svn add CC.txt
sshpass -e svn ci -m '3rd svn commit'

echo ddd > DD.txt
svn add DD.txt
sshpass -e svn ci -m '4th svn commit'

echo eee > EE.txt
svn add EE.txt
sshpass -e svn ci -m '5th svn commit'

cd /tmp
echo "Cloning svn as git"

sshpass -e git svn clone svn+ssh://localhost/tmp/myrepo_svn_WS myrepo_gitsvn

echo "Cloning a bare git local server"

git clone --bare myrepo_gitsvn myrepo_git_LS.git

echo "Adding a git local server remote to the gitsvn"

cd /tmp/myrepo_gitsvn
git remote add origingit file:///tmp/myrepo_git_LS.git

cd /tmp
cat > /tmp/myrepo_git_LS.git/hooks/post-update <<EOF
#!/usr/bin/env bash
export SSHPASS=${SSHPASS}
#export GIT_DIR="."
git update-server-info
export GIT_DIR=".git"
echo "post-update kicking in"
cd /tmp/myrepo_gitsvn
git pull --rebase origingit master
git log --graph --decorate --pretty=oneline --abbrev-commit --all --date-order
sshpass -e git svn rebase
sshpass -e git svn dcommit
sshpass -e git svn rebase
git log --graph --decorate --pretty=oneline --abbrev-commit --all --date-order
EOF
chmod +x /tmp/myrepo_git_LS.git/hooks/post-update

cd /tmp
echo "Cloning a git local server to git local working copy"

sshpass -e git clone ssh://localhost/tmp/myrepo_git_LS.git myrepo_git_wc

cd /tmp/myrepo_git_wc
echo "Working from git local working copy now"
git config user.name me
git config user.email me@myself.com

mkdir folder
echo hhh > folder/file.txt
git add folder/file.txt
git commit -m "1st git commit"
sshpass -e git push origin master

echo iiii >> folder/file.txt
git add folder/file.txt
git commit -m "2nd git commit"
sshpass -e git push origin master

echo "Simulating svn server offline; git wc commits get added"
mv /tmp/myrepo_svn_WS /tmp/.myrepo_svn_WS

echo jjj >> folder/file.txt
echo jjj > folder/file2.txt
git add folder/file*.txt
git commit -m "3rd git commit"
sshpass -e git push origin master

echo kkkk >> folder/file.txt
echo kkkk >> folder/file2.txt
git add folder/file*.txt
git commit -m "4th git commit"
sshpass -e git push origin master

echo "Simulating svn server back online; git wc commits get added"
mv /tmp/.myrepo_svn_WS /tmp/myrepo_svn_WS

#~ echo "Simulating merge conflict via git fetch"
#~ (cd /tmp/myrepo_gitsvn; git fetch origingit)

echo lll >> folder/file.txt
git add folder/file.txt
git commit -m "5th git commit"
sshpass -e git push origin master

echo mmm >> folder/file.txt
git add folder/file.txt
git commit -m "6th git commit"
sshpass -e git push origin master
Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278
  • possibly related: http://stackoverflow.com/questions/3855197/git-svn-rebase-is-failing-with-a-conflict-to-a-file-that-does-not-exist-in-git and https://github.com/abhikp/git-test/wiki/Getting-commits-from-SVN – sdaau Mar 14 '15 at 20:03

1 Answers1

0

So, I think I got somewhere - but I'm really not sure if this will work for all edge cases, so an eventual more erudite answer will be appreciated.

First, a note: you can obtain the logs with bash testrepo.sh 2>&1 | tee testrepo_MARK.log; and you can remove the control characters inserted by git remote from the logs with: sed -i 's/\x1b\[\x4b//g' testrepo*.log.

Anyways - apparently when doing git fetch, it adds a so-called local remote-tracking branch, which can be deleted as per How do I delete a Git branch both locally and remotely? (to not add that "local remote-tracking branch", one should apparently call git fetch <remote> --prune instead). But that is not enough if doing a recovery from a broken state; the broken state apparently means there is a record of an unsuccessful merge, that should be removed (for which git rebase --abort can be used, as the program itself recommends). So in short, the fix would be:

cd /tmp/myrepo_gitsvn
git branch --delete --remotes origingit/master
git rebase --abort

Here is a modification of the above script, that will allow for simulating the break and the recovery (just replace the respective parts in the OP script):

# ...
cd /tmp
cat > /tmp/myrepo_git_LS.git/hooks/post-update <<EOF
#!/usr/bin/env bash
export SSHPASS=${SSHPASS}
#export GIT_DIR="."
git update-server-info
export GIT_DIR=".git"
echo "post-update kicking in"
cd /tmp/myrepo_gitsvn
git svn info | grep Rev
git pull --rebase origingit master
git svn info | grep Rev
git log --graph --decorate --pretty=oneline --abbrev-commit --all --date-order
sshpass -e git svn rebase
sshpass -e git svn dcommit
sshpass -e git svn rebase
git log --graph --decorate --pretty=oneline --abbrev-commit --all --date-order
git svn info | grep Rev
EOF
chmod +x /tmp/myrepo_git_LS.git/hooks/post-update

# ...

echo "Simulating svn server back online; git wc commits get added"
mv /tmp/.myrepo_svn_WS /tmp/myrepo_svn_WS

DOCONFLICT=true
if [ "${DOCONFLICT}" = "true" ] ; then
echo "Simulating merge conflict via git fetch"
(cd /tmp/myrepo_gitsvn; git fetch origingit)
fi

echo lll >> folder/file.txt
git add folder/file.txt
git commit -m "5th git commit"
sshpass -e git push origin master

echo mmm >> folder/file.txt
git add folder/file.txt
git commit -m "6th git commit"
sshpass -e git push origin master

DOFIX=true
if [ "${DOCONFLICT}" = "true" ] ; then
if [ "${DOFIX}" = "true" ] ; then
  # https://stackoverflow.com/questions/2003505/delete-a-git-branch-both-locally-and-remotely/23961231#23961231
  (cd /tmp/myrepo_gitsvn;
  git branch --delete --remotes origingit/master;
  git rebase --abort;
  )
fi
fi

echo nnn >> folder/file.txt
git add folder/file.txt
git commit -m "7th git commit"
sshpass -e git push origin master

echo ooo >> folder/file.txt
git add folder/file.txt
git commit -m "8th git commit"
sshpass -e git push origin master

There are a few more commits, to test if the recovery holds; seemingly it does, because for the last commit, now this can be seen in the logs comparison:

/tmp/testrepo_meld_04.png

... so apart from a slight rearrangement, the log graph looks nearly the same. Also, note that as the added git svn info tells up, every time there is a "rewinding head to replay your work on top of it", git-svn actually brings the repository to commit 5 (which is the last one that was done solely in Subversion, before migrating to git-svn); not sure why this is. And at end, when the compacted log graph is shown after the final commit, all seems to look good:

testrepo_meld_05.png

Well, I hope this will help me get my actual repository fixed ...

Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278