Hello, Periodically, I sync the coreutils git repository to an otherwise read-only CVS repo, and use a cheap git tag named "cvs-head" to keep track of the point to which the latest sync operation has run. Then, after every sync-git-to-cvs operation, I run this: git-tag -f -m "most recent version that has been sync'd to cvs" cvs-head $sha1 Also periodically, I push my git working dir/repo to a public place, http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=summary ----------------- Just today, I have finally pushed tags to that public repo, including the "cvs-head" one (before there were no tags in the remote repo). But now, I've just done a local sync-to-cvs operation, which has resulted in moving that tag to point to a different point in the git repo. Here's the problem: When I try to push the new tags, git-push fails: $ git-push -f --tags ssh+git://git.sv.gnu.org/srv/git/coreutils master:refs/heads/master updating 'refs/tags/cvs-head' from 2fd3fd29a8b40be695bc2327c8cd3bd33e521100 to db18f53ffb221e9957124d8af81c11a7e350ac3b ... Total 1, written 1 (delta 0), reused 0 (delta 0) Unpacking 1 objects error: denying non-fast forward; you should pull first I get the same error also when using --force. Perhaps I shouldn't push the cvs-head tag at all. A few questions: - is there a way to say "push all tags matching /COREUTILS-*/" or to say "push all tags, except the ones on this list"? - is there a way to remove the cvs-head tag from the remote directory? Note: I don't have shell access there. I can request that someone with shell access do it, but shouldn't have to resort to that. - is there some way to make "git push" do what I want, and update the offending tag in the remote repo? Thanks for listening, Jim -
Possibly not, although it's nice to let others that use git to know
Here's a snippet from the default update hook we use on all our repos.
We explicitly deny any non-annotated tags from being pushed to the
central server and let rogue devs know why the push failed by writing
the error message to stderr so that it gets sent over the wire. I
believe this is still the default update-hook shipped with git.
---%<---%<----%<---
ref_type=$(git cat-file -t "$3")
# Only allow annotated tags in a shared repo
# Remove this code to treat dumb tags the same as everything else
case "$1","$ref_type" in
refs/tags/*,commit)
echo "*** Un-annotated tags are not allowed in this repo" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to
propagate." >&2
exit 1;;
I'm not sure if execution reaches the update hook when you're uploading
a tag that already exists. If it is, you could simply remove the
offending tag in the update-hook and exit 0 to make it work properly.
You can test this without shell-access on the remote system by setting
up a repo on your local machine, making some dummy commit, cloning it
and then hacking away on the hook while pushing to it from your local repo.
Other than that, push your tags manually by naming them explicitly on
the push-line, like so:
$ git push $remote_repo $tag_name
This is what I do whenever we cut a release. With a one tag per release,
it's not very troublesome at all, and the update-hook sends a nicely
formatted message of the changes since the last release (last tag
really, but it amounts to the same thing for us) to everyone involved.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
-
I think this is due to overeager receive.denyNonFastForwards
configuration setting at the repository you are pushing into.
I _think_ what receive-pack does in this case is totally wrong.
It should either:
(1) deny overwriting existing tags -- tags are meant to be
immutable so it should not allow them to be "updated"
regardless of fast-forwardness, or
(2) allow overwriting things under refs/tags/ without any
fast-forward checking. After all, a tag could point at a
tree or a blob, and there is no fast-forwardness among
trees.
The client side check in "git fetch" takes the latter viewpoint,
and I think we should be consistent with it.
Johannes, what do you think? Does the following patch look sane
to you?
---
diff --git a/receive-pack.c b/receive-pack.c
index 1a141dc..6c3de47 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -120,7 +120,7 @@ static int update(struct command *cmd)
"but I can't find it!", new_hex);
}
if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
- !is_null_sha1(old_sha1)) {
+ !is_null_sha1(old_sha1) && !strncmp(name, "refs/heads/", 11)) {
struct commit *old_commit, *new_commit;
struct commit_list *bases, *ent;
-
Hi, It does if you agree that (2) is correct. But I don't agree. cvs-head really should be a head IMHO, not a tag, because cvs-head really tracks a branch. I also think that git-fetch silently updating tags is wrong. Rather, it should warn that the tags are different. But I've been wrong before. Ciao, Dscho -
AFAIK, no one wants git-fetch to update tags _silently_. I expected it give a diagnostic and fail by default -- and it already does that. Pushing moved tags is serious business. I was hoping to be able to use --force to override that fail-safe. My goal is to maintain a symbolic reference "cvs-head" that points to the newest git trunk node that's been mirrored to a CVS repository. Without even considering any other option, I chose to use a lightweight tag for that purpose, since I have a conceptual view that it's a label I can move from one referent to another. It strikes me as counter-intuitive to use a temporary git "branch" that way. Would that even work, removing it and recreating it all the time? Hmm.. or maybe you mean to create the branch once and then to merge from the trunk repeatedly. That seems like unnecessary work, when all I want is a movable label. I admit that I like the idea of release tags being immutable, but even there, it's happened that I've made-but-not-published a release, then realized that it wasn't quite complete. I was glad to be able to go back and re-tag after making corrections. I wouldn't mind having a way to specify that a pushed tag is *not* immutable, with the default being it is immutable. -
Hi, Hmmm. Probably Junio's patch is correct after all, since tags are special creatures: you do not expect them to change, but if, they can change Yes, it would. Remember: a branch in git is just a named ref. It literally used to be a 41-byte file pointing to the tip of the branch in the ancestor graph. And you can update it with git-update-ref. So, a branch in git is very much the movable label you are looking for. Ciao, Dscho -
Well remember that all heads are simply references into the DAG, they are all labels. 'heads' you are allowed to move and change, commit to etc, but they are still just name -> sha1 mechanisms. If the merge is a ff then there is no work. You could always use -apw -
