Discussion:
git-fetch remote tag to local branch fails
Klas Lindberg
2008-06-24 12:17:39 UTC
Permalink
Hi

I have a repository "bogustree" that contains tags "test_tag" and
"foo_tag" (both on the same branch, with "test_tag" pointing to an
older commit).
I also have repository "R", which contains "test_tag" from "bogustree"
and a branch "b" created from "test_tag". The active branch in R is
"master".

Now I want to do the following from R:

git-fetch bogustree refs/tags/foo_tag:refs/heads/b

but this fails with the message given below. The interesting part is
that git-fetch tries to write a "non-commit object" and indeed I have
no idea what this thing is (the commit pointed to by "foo_tag" has
commit ID cab0a25388f1884a1ab16bd0d66f877c0b36f1d5). Another
interesting detail is that the command fails and then continues
anyway. That seems wrong in itself.

# remote: Counting objects: 6, done.
# remote: Compressing objects: 100% (2/2), done.
# remote: Total 4 (delta 0), reused 0 (delta 0)
# Unpacking objects: 100% (4/4), done.
# error: Trying to write non-commit object
5f61233bc5dad0f3e25ecea65457f5bb528174d2 to branch refs/heads/B
# From /home/qliklas/bogustree/b/b
# 72f0622..5f61233 foo_tag -> b
# From /home/qliklas/bogustree/b/b
# * [new tag] foo_tag -> foo_tag
# * [new tag] test_tag -> test_tag

Why can't I fetch like this? The manual page for git-fetch says that

<refspec>
The canonical format of a <refspec> parameter is +?<src>:<dst>;
that is, an optional plus +, followed by the source ref,
followed by a colon :, followed by the destination ref.

The remote ref that matches <src> is fetched, and if <dst> is
not empty string, the local ref that matches it is fast
forwarded using <src>. Again, if the optional plus + is used,
the local ref is updated even if it does not result in a fast
forward update.

so I think it should be OK?

BR / Klas
Santi Béjar
2008-06-24 13:38:12 UTC
Permalink
Post by Klas Lindberg
Hi
I have a repository "bogustree" that contains tags "test_tag" and
"foo_tag" (both on the same branch, with "test_tag" pointing to an
older commit).
I also have repository "R", which contains "test_tag" from "bogustree"
and a branch "b" created from "test_tag". The active branch in R is
"master".
git-fetch bogustree refs/tags/foo_tag:refs/heads/b
but this fails with the message given below. The interesting part is
that git-fetch tries to write a "non-commit object" and indeed I have
no idea what this thing is (the commit pointed to by "foo_tag" has
commit ID cab0a25388f1884a1ab16bd0d66f877c0b36f1d5).
non-commit object is an object that is not a commit, like a tag, a
blob or a tree, and you are trying to write a tag in refs/heads/. Only
commits objects (no tags) are allowed in refs/heads/.
Post by Klas Lindberg
Another
interesting detail is that the command fails and then continues
anyway. That seems wrong in itself.
# remote: Counting objects: 6, done.
# remote: Compressing objects: 100% (2/2), done.
# remote: Total 4 (delta 0), reused 0 (delta 0)
# Unpacking objects: 100% (4/4), done.
# error: Trying to write non-commit object
5f61233bc5dad0f3e25ecea65457f5bb528174d2 to branch refs/heads/B
# From /home/qliklas/bogustree/b/b
# 72f0622..5f61233 foo_tag -> b
# From /home/qliklas/bogustree/b/b
# * [new tag] foo_tag -> foo_tag
# * [new tag] test_tag -> test_tag
Are you sure it is written as a branch? What is the output of "git tag
-l" and "git branch -a"?
Post by Klas Lindberg
Why can't I fetch like this? The manual page for git-fetch says that
<refspec>
The canonical format of a <refspec> parameter is +?<src>:<dst>;
that is, an optional plus +, followed by the source ref,
followed by a colon :, followed by the destination ref.
The remote ref that matches <src> is fetched, and if <dst> is
not empty string, the local ref that matches it is fast
forwarded using <src>. Again, if the optional plus + is used,
the local ref is updated even if it does not result in a fast
forward update.
so I think it should be OK?
as long as <src> are commit objects.

Santi
Klas Lindberg
2008-06-24 14:01:13 UTC
Permalink
Hello
git tag -l
foo_tag
test_tag
git branch -a
At this point, I can create the branch "b" from "foo_tag", so the
fetch did get me a remote tag. It just didn't update a local branch
with the contents (or create a new one).

Something that also confuses me is that if branch "b" already exists, t=
hen
git-pull bogustree refs/tags/foo_tag:refs/heads/b
actually does update branch "b". I find the behaviour quite inconsisten=
t.

Unfortunately it isn't a solution for me to fetch tags and then create
branches from the tags. I need to be able to update existing branches,
and I have to do that without first making such a branch the current
branch.

Any suggestions?

/Klas
Post by Klas Lindberg
Hi
I have a repository "bogustree" that contains tags "test_tag" and
"foo_tag" (both on the same branch, with "test_tag" pointing to an
older commit).
I also have repository "R", which contains "test_tag" from "bogustre=
e"
Post by Klas Lindberg
and a branch "b" created from "test_tag". The active branch in R is
"master".
git-fetch bogustree refs/tags/foo_tag:refs/heads/b
but this fails with the message given below. The interesting part is
that git-fetch tries to write a "non-commit object" and indeed I hav=
e
Post by Klas Lindberg
no idea what this thing is (the commit pointed to by "foo_tag" has
commit ID cab0a25388f1884a1ab16bd0d66f877c0b36f1d5).
non-commit object is an object that is not a commit, like a tag, a
blob or a tree, and you are trying to write a tag in refs/heads/. Onl=
y
commits objects (no tags) are allowed in refs/heads/.
Post by Klas Lindberg
Another
interesting detail is that the command fails and then continues
anyway. That seems wrong in itself.
# remote: Counting objects: 6, done.
# remote: Compressing objects: 100% (2/2), done.
# remote: Total 4 (delta 0), reused 0 (delta 0)
# Unpacking objects: 100% (4/4), done.
# error: Trying to write non-commit object
5f61233bc5dad0f3e25ecea65457f5bb528174d2 to branch refs/heads/B
# From /home/qliklas/bogustree/b/b
# 72f0622..5f61233 foo_tag -> b
# From /home/qliklas/bogustree/b/b
# * [new tag] foo_tag -> foo_tag
# * [new tag] test_tag -> test_tag
Are you sure it is written as a branch? What is the output of "git ta=
g
-l" and "git branch -a"?
Post by Klas Lindberg
Why can't I fetch like this? The manual page for git-fetch says that
<refspec>
The canonical format of a <refspec> parameter is +?<src=
:<dst>;
Post by Klas Lindberg
that is, an optional plus +, followed by the source ref=
,
Post by Klas Lindberg
followed by a colon :, followed by the destination ref.
The remote ref that matches <src> is fetched, and if <d=
st> is
Post by Klas Lindberg
not empty string, the local ref that matches it is fast
forwarded using <src>. Again, if the optional plus + is=
used,
Post by Klas Lindberg
the local ref is updated even if it does not result in =
a fast
Post by Klas Lindberg
forward update.
so I think it should be OK?
as long as <src> are commit objects.
Santi
Santi Béjar
2008-06-24 14:27:49 UTC
Permalink
Post by Klas Lindberg
Hello
git tag -l
foo_tag
test_tag
git branch -a
empty?
Post by Klas Lindberg
At this point, I can create the branch "b" from "foo_tag", so the
fetch did get me a remote tag. It just didn't update a local branch
with the contents (or create a new one).
Something that also confuses me is that if branch "b" already exists, then
git-pull bogustree refs/tags/foo_tag:refs/heads/b
actually does update branch "b". I find the behaviour quite inconsistent.
You asked explicitly to update branch b with :refs/heads/b.
Post by Klas Lindberg
Unfortunately it isn't a solution for me to fetch tags and then create
branches from the tags. I need to be able to update existing branches,
and I have to do that without first making such a branch the current
branch.
If you have to update existing branches from remote branches you can:

git fetch <remote> refs/heads/<remotebranch>:refs/heads/<localbranch>

But normally you have some remote tracking branches, such as how the
"origin" remote repository is configured.

Updating from remote tags is not normal, since tags are not supposed to change.

Can you explain why you have to do it this way? Or the whole workflow?

Santi

P.D.: Please, do not toppost.
Klas Lindberg
2008-06-24 15:31:49 UTC
Permalink
Post by Santi Béjar
Post by Klas Lindberg
Post by Santi Béjar
git branch -a
empty?
Sorry, my mistake. It lists "master"
Post by Santi Béjar
Post by Klas Lindberg
Post by Santi Béjar
git-pull bogustree refs/tags/foo_tag:refs/heads/b
actually does update branch "b". I find the behaviour quite inconsistent.
You asked explicitly to update branch b with :refs/heads/b.
I'm not sure what you mean. I asked it to update local branch "b"
against remote tag "foo_tag" and it did just that. I find it
inconsistent that pull can do this, but fetch can't.
Post by Santi Béjar
Can you explain why you have to do it this way? Or the whole workflow?
I am looking into the possibility of writing a tool that handles
configurations of trees. For instance, I want the tool to be able to
consume some version of a configuration and create, update or reset
branches in other trees accordingly.
The main stumbling block is actually that a lot of git commands have
side effects on the working tree (usually because they do something
with a "current" branch). In my mind, the user should be able to
select a configuration that effectively fast forwards branches in some
trees and resets branches in others -- all of it without touching any
working trees (unless there is an explicit checkout).
The example in this case is that fetching tags to update a branch
isn't possible. Pulling *is* possible, but would also update the
current branch and the working tree.

/Klas
Klas Lindberg
2008-06-24 15:36:56 UTC
Permalink
Post by Klas Lindberg
I'm not sure what you mean. I asked it to update local branch "b"
against remote tag "foo_tag" and it did just that. I find it
inconsistent that pull can do this, but fetch can't.
I'm sorry. That was plain wrong. It doesn't update the branch from the
remote tag when I pull.

Oh well...
Santi Béjar
2008-06-24 16:11:27 UTC
Permalink
Post by Klas Lindberg
Post by Santi Béjar
Can you explain why you have to do it this way? Or the whole workflow?
I am looking into the possibility of writing a tool that handles
configurations of trees.
Maybe you should be using the plumbing commands.
Post by Klas Lindberg
For instance, I want the tool to be able to
consume some version of a configuration and create, update or reset
branches in other trees accordingly.
What are the "other trees"?

Do you mean this?

1. You have a repository with different branches as:
master
tree1
tree2
..

2. You want /path/to/tree1 to always checkout tree1
and the same for treeN

Then

3. In /path/to/treeN/.. you do:
$ git clone /path/to/repo treeN
$ git checkout -b treeN origin/treeN

4. To keep uptodate:
$ git pull

5. The branches for the other trees are always uptodate in origin/*.
Post by Klas Lindberg
The main stumbling block is actually that a lot of git commands have
side effects on the working tree (usually because they do something
with a "current" branch).
Sure. So you have to choose those that don't have these "side
effects", you have plenty of them, mainly in the low-level, plumbing
commands.
Post by Klas Lindberg
In my mind, the user should be able to
select a configuration that effectively fast forwards branches in some
trees and resets branches in others -- all of it without touching any
working trees (unless there is an explicit checkout).
Well, if you touch the current branch, for sure, you want to update
the working tree.

Maybe you want to keep your local branches up to date with respect
their tracking branch?
Post by Klas Lindberg
The example in this case is that fetching tags to update a branch
isn't possible.
I don't see the point updating a branch with a tag, but you can make a
tool to update a branch with a tag, see for example
contrib/examples/git-fetch.sh.

Santi
Klas Lindberg
2008-06-25 08:50:06 UTC
Permalink
Post by Santi Béjar
Post by Klas Lindberg
I am looking into the possibility of writing a tool that handles
configurations of trees.
Maybe you should be using the plumbing commands.
Yes. It looks like it.
Post by Santi Béjar
Post by Klas Lindberg
For instance, I want the tool to be able to
consume some version of a configuration and create, update or reset
branches in other trees accordingly.
What are the "other trees"?
One tree tracks a configuration file that just contains specs for
other trees. The idea is something like this: Given a refspec on the
configuration tree, git-view the configuration file and use the
contained refspecs to clone/pull/fetch/reset/whatever a bunch of other
trees.

Note that I'm not trying to solve the problem addressed by the
submodules system in git; I need configuration management.
Post by Santi Béjar
Maybe you want to keep your local branches up to date with respect
their tracking branch?
Well yes, but that is only half of it. One of the scenarios I'm
pondering is this: A user wants to take an old configuration based on
tags and try some use case that breaks a newer configuration. After
the checkout, the working trees will not be "on" any branches (what's
the word for that?). Unfortunately, most people seem to think that
everything in a VCS happens on a branch. A lot of people will
incorrectly assume that they are still on their "working branch"
because they didn't check out a different branch! They checked out a
tag and, like myself, have muddy ideas about what that actually means
in relation to branches. I'd prefer to not have to tell them to try
git-lost-found on a 40 different trees to recover commits that they
made on non-branches.

I'll have to think more about this. It's not a functionality
shortcoming, but a UI one.
Post by Santi Béjar
I don't see the point updating a branch with a tag, but you can make a
tool to update a branch with a tag, see for example
contrib/examples/git-fetch.sh.
Thank you. I'll have a look at that, but after our conversation I
think I was mentally stuck in the land of some other VCS. I know
perfectly well that a tag is not just a marker along some branch, but
I realize now that I was thinking of it as if it was.

/Klas
Jakub Narebski
2008-06-25 09:10:38 UTC
Permalink
Post by Klas Lindberg
Note that I'm not trying to solve the problem addressed by the
submodules system in git; I need configuration management.
Why not use one of existing tools (see InterfacesFrontendsAndTools
page on Git Wiki, http://git.or.cz/gitwiki/), like IsiSetup, or
etckeeper?
--
Jakub Narebski
Poland
ShadeHawk on #git
Michael J Gruber
2008-06-24 14:57:02 UTC
Permalink
Post by Klas Lindberg
Hello
git tag -l
foo_tag
test_tag
git branch -a
At this point, I can create the branch "b" from "foo_tag", so the
fetch did get me a remote tag. It just didn't update a local branch
with the contents (or create a new one).
Something that also confuses me is that if branch "b" already exists, then
git-pull bogustree refs/tags/foo_tag:refs/heads/b
actually does update branch "b". I find the behaviour quite inconsistent.
You tell git to fetch everything up to the tag you specify, to store
those refs into branch b, and then to merge into the current branch.
This is what git did (assuming you see the merge in the current branch;
if it's b then it has been fast forwarded already).
Post by Klas Lindberg
Unfortunately it isn't a solution for me to fetch tags and then create
branches from the tags. I need to be able to update existing branches,
and I have to do that without first making such a branch the current
branch.
If I try what you described (using git 1.5.6) in a fresh repo (with one
empty commit) I get:

git fetch ../fromrepo refs/tags/testtag:refs/heads/newbranch
warning: no common commits
remote: Counting objects: 18, done.
remote: Compressing objects: 100% (18/18), done.
remote: Total 18 (delta 9), reused 0 (delta 0)
Unpacking objects: 100% (18/18), done.
From ../fromrepo
* [new branch] testtag -> newbranch
* [new tag] testtag -> testtag

I see a new branch, disconnected from master (no common commits), and a
new tag pointing to the head of newbranch. All is well here. Maybe you
can set-up a minimal example or share a repo which exposes your problem?

Michael
Loading...