可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
While working on a usual git repository a local branch usually tracks a corresponding remote upstream branch. This way I can easily see, whether I am ahead or behind of my upstream branch and therefore if I need to push or pull to bring them in sync. Also my prompt immediately shows this state, which is very convenient.
Now I am working on a SVN repository using git-svn
. I used --prefix=svn
for the clone, therefore git branch -r
lists svn/trunk
as a remote branch, but (although git svn rebase
works without problems) it is not configured as an upstream branch for my master branch.
I tried to set the tracking information manually but it failed:
$ git branch -r
svn/trunk
$ git branch --set-upstream-to=svn/trunk
fatal: Cannot setup tracking information; starting point 'svn/trunk' is not a branch.
Is there some way to track an svn upstream branch?
Is there some other easy way to know whether I am ahead or behind to that branch? (Looking at gitk --all
is currently the only way I am aware of.)
Is there even some way to make my (bash __git_ps1
) prompt show that information?
$ git --version
git version 1.9.0.msysgit.0
回答1:
This seems to be a bug introduced in git 1.9, since --set-upstream-to
worked before exactly as you mention.
And strace
displays correct locating and reading of the upstream branch ref, then however it's ignored for some reason.
My workaround for this issue is manual editing of .git/config
:
$ cat >> .git/config << EOF
[branch "master"]
remote = .
merge = refs/svn/trunk
rebase = true
EOF
— which should be equivalent to:
git branch --set-upstream-to=svn/trunk master
&& git config branch.master.rebase true
(which you'll want with svn anyway)
— but is not, because of a bug! "Of course my refs/svn/trunk
is a branch!" you say, and edit the config directly (with just a little bit of gentle force).
Your svn trunk could be named differently in git depending on how you cloned the repo (-s
, -T
, --prefix
options to git svn clone
). Just do a git branch -avv
and find the correct one. For example, one possible name is refs/remotes/git-svn
; or refs/svn/trunk
as above; or even something else.
Update Nov 2015
I still reproduce this on git version 2.1.4
. Anyone to bother file a bug report?
回答2:
git-svn
will store the configuration data in .git/config
, for example in one of my repo the config is like:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[svn-remote "svn"]
url = http://svn.repo.com/repos/myrepo
fetch = trunk:refs/remotes/trunk
branches = branches/*:refs/remotes/*
tags = tags/*:refs/remotes/tags/*
In the [svn-remote "svn"]
section you can see all the git-svn
configurations. In the branches
section you see all the branches on the remote svn
repo.
When I need to follow a svn
branch in my local git
repo I usually do these steps:
- I check that the
config
is correctly configured with all the branches
and the tags
.
- I do a
git svn fetch
, in that way git will fetch all the data in the repo for all the branches
I check that all the branches
/ tags
are present as output of git branch -a
, for example:
master
prod
scenarioParametro
remotes/tags/alpha-1
remotes/trunk
I create a local git branch
to track a remote one with:
git branch alpha-1 remotes/tags/alpha-1 --track
In this way the newly created alpha-1
branch will follow the remotes/tags/alpha-1
, and you can do the rebase
and dcommit
commands.
回答3:
This was still a problem for me using git 1.9.5.
And I did not get any of the solutions mentioned here to work, but this worked:
git rebase origin/remote-branch-name
After that git svn dcommit -n
shows that it will indeed commit to that svn branch.
Update: I had the same problem again and this time the above didn't work. I just got the message: Current branch master is up to date.
However using:
git rebase -i origin/remote-branch-name
forced the rebase anyway and after that the upstream was set correctly.
回答4:
Since nobody answered this:
Is there some other easy way to know whether I am ahead or behind to that branch?
Yes, it is. You can just use the general notion GIT uses for comparing refs also in this case. It’s ref_from..ref_to
E.g.:
git log master..svn/trunk
– will give you all commits from svn/trunk
that are missing in your master
. I.e. incomming changes.
git log svn/trunk..master
– will give you all commits from master
that are missing in svn/trunk
. I.e. outgoing changes.
Further explanation of the general syntax: here on SO and in the official GIT documentation