问题
I have a remote tracking branch tracked locally in my local repository using 'git branch -b branch-name origin/branch-name'. My remote branch is test2/test2 (origin/branch-name) which is being tracked locally as test2.
The origin is also named test2. I haven't checked-out my local tracking branch test2.
When i do a 'git pull origin remote-branch:local-tracked-branch' i get this error
[test2]$ git pull test2 test2:test2 From /gitvobs/git_bare/test2 ! [rejected] test2 -> test2 (non fast forward)
Whereas when i checkout my local tracking branch test2 and do pull 'git pull origin local-tracked-branch' i don't get the error and i do a pull using 'git pull test2 test2'
From /gitvobs/git_bare/test2 * branch test2 -> FETCH_HEAD Auto-merging a.txt Automatic merge failed; fix conflicts and then commit the result.
i know that adding a + (git pull test2 +test2:test2) would help but it overwrites local changes.
So how do i know which of my local branches are created by me locally using 'git branch new-branch-name' or tracked locally from remote branches using git branch -b branch-name origin/branch-name'?
回答1:
Independently of the list of tracked branched (which you can see with git config -l
), a "non-fast-forward" message means cannot merge the remote branch (i.e. the local copy of the fetched commit of the remote branch) in your branch because:
- your branch has commits of its own
- the remote branch has new commits since the last pull
so:
--last pull
|
v
x-x-x-x-x <--test2
\
-y-y-y <-- test2/test2
Whereas this would have been a fast-forward merge
--last pull
|
v
x-x <--test2
\
-y-y-y <-- test2/test2
So:
git checkout test2
git fetch test2 test2
git merge test2/test2
#fix conflicts
git commit
And please, do call your remote repo any other name than test2. That is way too many test2 here ;)
Now for the list of remote branches tracked in your local repo:
git config --get-regexp branch..*
回答2:
git pull Confusion
Over-specificity
Your git pull command includes too much information.
[test2]$ git pull test2 test2:test2
From /gitvobs/git_bare/test2
! [rejected] test2 -> test2 (non fast forward)i know that adding a + (git pull test2 +test2:test2) would help but it overwrites local changes.
This is what your command means:
# *------------ (1) remote repository name
# / *------- (2) ref in remote repository
# / / *-- (3) ref in local repository
# / / /
git pull test2 test2:test2
# Means this: From remote repository `test2` (1),
# fetch branch `test2` (2), store it in local branch `test2` (3), then
# merge the fetched history into HEAD.
You are telling git pull to overwrite your local test2
branch with whatever the remote has on its test2
branch and then merge that with HEAD. You probably do not want to include the destination part of the refspec (the :test2
).
If the local branch you have checked out is configured to track something (see the “Branches: …” below), just do
git pull
If you need to supply (or override) a remote and repository, just supply the remote name/url and the local branch on the remote (leave off the final part of the refspec):
git pull test2 test2
Pull Into a Branch That is Not Checked Out
git pull is (as mentioned above) a combination of git fetch and git merge (or git rebase).
In general, a merge might involve conflict resolution. Conflict resolution requires a working tree. Therefore, it is not possible to perform a normal merge operation without a working tree. This means that your current HEAD has to be one of parents of the merge (it will be the first parent). Doing a rebase also needs a working tree for conflict resolution.
Since a pull involves a merge or rebase, it is not possible to pull into a local branch that is not checked out. You can only pull into the currently checked out branch.
Branches: Local, Tracking, Remote Tracking
The various types of Git branches are all the same underlying object: refs. Refs live in the refs/
namespace in $GIT_DIR/refs/
and $GIT_DIR/packed-refs
.
- “Local” branches live in the
refs/heads/
namespace.- To examine the
test2
local branch ref:git show-ref refs/heads/test2
, orcat .git/refs/heads/test2
, orgrep -F refs/heads/test2 .git/packed-refs
- To examine the
- “Remote Tracking” branches live in the
refs/remotes/<remote-name>/
namespaces.- Remote tracking branches are local copies of branches from a remote repository.
- The name “remote tracking” makes sense when you think of it like this, but it can be confused with the unfortunately named
--track
functionality of git branch and git checkout (see the final branch type).
- The name “remote tracking” makes sense when you think of it like this, but it can be confused with the unfortunately named
- To examine the
test2
remote tracking branch ref:git show-ref refs/remotes/test2/test2
, orcat .git/refs/remotes/test2/test2
, orgrep -F refs/remotes/test2/test2 .git/packed-refs
- Remote tracking branches are local copies of branches from a remote repository.
Local branches that track another branch are normal local branches (in
refs/heads/
) that have extra configuration in$GIT_DIR/config
:[branch "test2"] remote = test2 merge = refs/heads/test2
It is important to note that the
merge
(orrebase
) configuration option names a ref on the remote. Sorefs/heads/test2
here means the local branchtest2
found on the remotetest2
. The special remote name.
can be used to refer to local branches in the local repository.- The purpose of local branches that “track” some other branch is to make it easy to just type
git pull
and have it merge in (or rebase on top of) the history in some other branch.
- The purpose of local branches that “track” some other branch is to make it easy to just type
You said that you wanted to distinguish plain plain local branches from local branches that track some other branch. You can do this by looking for the branch configuration in the $GIT_DIR/config
file.
You might use git config to do this:
branch_tracks_something() {
{
git config branch."$1".merge ||
git config branch."$1".rebase
} >/dev/null 2>&1
}
# test local branch
branch_tracks_something test2 && echo 'test2 tracks something' || echo 'test2 does not track anything'
Or, if you have Git 1.6.3 or later, you can use the %(upstream)
format of git for-each-ref:
{ echo 'show_ref_desc() {
case "$1" in
refs/heads/*)
t=''
test -n "$2" && t=" (tracks $2)"
echo "local: $1$t"
;;
refs/remotes/*)
echo "remote tracking: $1"
;;
*)
echo "other: $1"
;;
esac
}'; git for-each-ref --shell --format='show_ref_desc %(refname) %(upstream)'; } |
sh
The output looks like this:
local: refs/heads/test2 (tracks refs/remotes/test2/test2)
remote tracking: refs/remotes/test2/HEAD
remote tracking: refs/remotes/test2/test2
来源:https://stackoverflow.com/questions/2887242/how-to-find-if-a-branch-is-a-locally-tracked-branch-or-user-created-local-branch