git svn系统出现意外的合并错误? [英] Unexpected merge error in a git svn system?

查看:96
本文介绍了git svn系统出现意外的合并错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些有点复杂的设置(如,模拟本地进程 - 包括 myrepo_svn_WS 离线。如果您按原样使用脚本,您会注意到系统可以从SVNWS服务器离线恢复,并且该情况下的日志为



我没有想太多,因为我没有想到 git-svn 作为分支;但是这里有一个子问题: git-svn origingit / master ,哪一个是分支?



该部分结束于此:



请注意,最终,未失败的进程将日志图形树显示为压缩或展平(即没有分支伸出) - 而此时失败的进程不会没有抱怨错误,但将日志图形树显示为分支。

只有在'6th git commit'后才会出现问题:

sed -i's / \x1b\ [\x4b // g'testrepo * .log



无论如何 - 显然当做 git fetch 时,它会添加一个所谓的本地远程跟踪分支,可以根据



...所以除了轻微的重新排列之外,日志图看起来几乎相同。另外请注意,当添加 git svn info 时,每次有一个回放头重播你的工作时,git-svn实际上会带来仓库提交5(这是在迁移到git-svn之前完成在Subversion中完成的最后一个);不知道这是为什么。最后,在最终提交之后显示压缩日志图时,所有内容看起来都不错:

p>

嗯,我希望这会帮助我修复我的实际存储库...


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:

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):

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:

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':

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

解决方案

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:

... 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:

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

这篇关于git svn系统出现意外的合并错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆