* checkout new branch tracks wrong remote (bug?) @ 2011-03-30 2:27 chris 2011-03-30 14:59 ` Jeff King 0 siblings, 1 reply; 13+ messages in thread From: chris @ 2011-03-30 2:27 UTC (permalink / raw) To: git I have two remotes configured. One is "origin" which has a local tracking branch "master" for "origin/master". The other is "mirror" which has option mirror = true While on the local branch master, I issue the command: $ git checkout -b wip The branch "wip" is created and oddly configured to track the "mirror" remote. Here is the .git/config after the "wip" branch was created: [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* url = ssh://myserver.com/srv/git/myproject.git [branch "master"] remote = origin merge = refs/heads/master [remote "mirror"] url = ssh://chris@myserver.com/srv/git/mirrors/chris/myproject.git fetch = +refs/*:refs/* mirror = true [branch "wip"] remote = mirror merge = refs/heads/master $ git --version git version 1.7.4.1 $ git config branch.autosetupmerge $ I do not expect this "wip" branch to be tracking the "mirror" remote, but rather "origin", according to the documentation. chris ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: checkout new branch tracks wrong remote (bug?) 2011-03-30 2:27 checkout new branch tracks wrong remote (bug?) chris @ 2011-03-30 14:59 ` Jeff King 2011-03-30 19:51 ` [PATCH 0/3] better "remote add --mirror" semantics Jeff King 0 siblings, 1 reply; 13+ messages in thread From: Jeff King @ 2011-03-30 14:59 UTC (permalink / raw) To: chris; +Cc: git On Wed, Mar 30, 2011 at 02:27:31AM +0000, chris wrote: > I have two remotes configured. > > One is "origin" which has a local tracking branch "master" for "origin/master". > > The other is "mirror" which has option mirror = true > > While on the local branch master, I issue the command: > > $ git checkout -b wip > > The branch "wip" is created and oddly configured to track the "mirror" remote. Right. You are creating a branch from "refs/heads/master" (the currently checked out branch). So the setup_tracking code will look for any remote which writes a tracking branch into refs/heads/master according to the configuration. Your mirror config looks like this: > [remote "mirror"] > url = ssh://chris@myserver.com/srv/git/mirrors/chris/myproject.git > fetch = +refs/*:refs/* > mirror = true meaning that a fetch of the mirror remote will write the mirror's refs/heads/master into our local refs/heads/master. IOW, your master branch is actually configured as a remote tracking branch of the mirror (which is probably not what you want; see below). > I do not expect this "wip" branch to be tracking the "mirror" remote, but rather > "origin", according to the documentation. In the absence of the mirror remote, it would not track anything. You are branching from a _local_ branch, so there is no remote to track. I think what you really want is: git checkout -b wip origin/master All of that being said, I'm not sure your config makes sense: > [remote "origin"] > fetch = +refs/heads/*:refs/remotes/origin/* > url = ssh://myserver.com/srv/git/myproject.git > [remote "mirror"] > url = ssh://chris@myserver.com/srv/git/mirrors/chris/myproject.git > fetch = +refs/*:refs/* > mirror = true Your mirror is configured to overwrite everything in refs/ if you fetch from it. Meaning it will throw away anything you fetched from "origin", as well as any local work. So this config is probably not what you want. I'm guessing what you really wanted is a remote only for pushing to, and created it with: git remote add --mirror mirror ssh://... The --mirror option has problems with that case. See this thread: http://article.gmane.org/gmane.comp.version-control.git/161653 which has some suggestions, but nothing has been implemented yet. Probably it makes sense to allow --mirror=fetch and --mirror=push, but there is an open question of what just "--mirror" should do. -Peff ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/3] better "remote add --mirror" semantics 2011-03-30 14:59 ` Jeff King @ 2011-03-30 19:51 ` Jeff King 2011-03-30 19:52 ` [PATCH 1/3] remote: disallow some nonsensical option combinations Jeff King ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Jeff King @ 2011-03-30 19:51 UTC (permalink / raw) To: chris; +Cc: Jan Hudec, git On Wed, Mar 30, 2011 at 10:59:08AM -0400, Jeff King wrote: > All of that being said, I'm not sure your config makes sense: > > > [remote "origin"] > > fetch = +refs/heads/*:refs/remotes/origin/* > > url = ssh://myserver.com/srv/git/myproject.git > > [remote "mirror"] > > url = ssh://chris@myserver.com/srv/git/mirrors/chris/myproject.git > > fetch = +refs/*:refs/* > > mirror = true > > Your mirror is configured to overwrite everything in refs/ if you fetch > from it. Meaning it will throw away anything you fetched from "origin", > as well as any local work. So this config is probably not what you want. > > I'm guessing what you really wanted is a remote only for pushing to, and > created it with: > > git remote add --mirror mirror ssh://... > > The --mirror option has problems with that case. See this thread: > > http://article.gmane.org/gmane.comp.version-control.git/161653 Here is a patch series which I think improves the situation. +cc Jan Hudec from the mentioned thread. [1/3]: remote: disallow some nonsensical option combinations [2/3]: remote: separate the concept of push and fetch mirrors [3/3]: remote: deprecate --mirror -Peff ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/3] remote: disallow some nonsensical option combinations 2011-03-30 19:51 ` [PATCH 0/3] better "remote add --mirror" semantics Jeff King @ 2011-03-30 19:52 ` Jeff King 2011-03-30 19:53 ` [PATCH 2/3] remote: separate the concept of push and fetch mirrors Jeff King 2011-03-30 19:53 ` [PATCH 3/3] remote: deprecate --mirror Jeff King 2 siblings, 0 replies; 13+ messages in thread From: Jeff King @ 2011-03-30 19:52 UTC (permalink / raw) To: chris; +Cc: Jan Hudec, git It doesn't make sense to use "-m" on a mirror, since "-m" sets up the HEAD symref in the remotes namespace, but with mirror, we are by definition not using a remotes namespace. Similarly, it does not make much sense to specify refspecs with --mirror. For a mirror you plan to push to, those refspecs will be ignored. For a mirror you are fetching from, there is no point in mirroring, since the refspec specifies everything you want to grab. There is one case where "--mirror -t <X>" would be useful. Because <X> is used as-is in the refspec, and because we append it to to refs/, you could mirror a subset of the hierarchy by doing: git remote add --mirror -t 'tags/*' But using anything besides a single branch as an argument to "-t" is not documented and only happens to work, so closing it off is not a serious regression. Signed-off-by: Jeff King <peff@peff.net> --- builtin/remote.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/builtin/remote.c b/builtin/remote.c index b71ecd2..2e25c6a 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -161,6 +161,11 @@ static int add(int argc, const char **argv) if (argc < 2) usage_with_options(builtin_remote_add_usage, options); + if (mirror && master) + die("specifying a master branch makes no sense with --mirror"); + if (mirror && track.nr) + die("specifying branches to track makes no sense with --mirror"); + name = argv[0]; url = argv[1]; -- 1.7.4.2.8.g3ccd6 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-30 19:51 ` [PATCH 0/3] better "remote add --mirror" semantics Jeff King 2011-03-30 19:52 ` [PATCH 1/3] remote: disallow some nonsensical option combinations Jeff King @ 2011-03-30 19:53 ` Jeff King 2011-03-30 20:45 ` Junio C Hamano 2011-03-30 19:53 ` [PATCH 3/3] remote: deprecate --mirror Jeff King 2 siblings, 1 reply; 13+ messages in thread From: Jeff King @ 2011-03-30 19:53 UTC (permalink / raw) To: chris; +Cc: Jan Hudec, git git-remote currently has one option, "--mirror", which sets up mirror configuration which can be used for either fetching or pushing. It looks like this: [remote "mirror"] url = wherever fetch = +refs/*:refs/* mirror = true However, a remote like this can be dangerous and confusing. Specifically: 1. If you issue the wrong command, it can be devastating. You are not likely to "push" when you meant to "fetch", but "git remote update" will try to fetch it, even if you intended the remote only for pushing. In either case, the results can be quite destructive. An unintended push will overwrite or delete remote refs, and an unintended fetch can overwrite local branches. 2. The tracking setup code can produce confusing results. The fetch refspec above means that "git checkout -b new master" will consider refs/heads/master to come from the remote "mirror", even if you only ever intend to push to the mirror. It will set up the "new" branch to track mirror's refs/heads/master. 3. The push code tries to opportunistically update tracking branches. If you "git push mirror foo:bar", it will see that we are updating mirror's refs/heads/bar, which corresponds to our local refs/heads/bar, and will update our local branch. To solve this, we split the concept into "push mirrors" and "fetch mirrors". Push mirrors set only remote.*.mirror, solving (2) and (3), and making an accidental fetch write only into FETCH_HEAD. Fetch mirrors set only the fetch refspec, meaning an accidental push will not force-overwrite or delete refs on the remote end. The new syntax is "--mirror=<fetch|push>". For compatibility, we keep "--mirror" as-is, setting up both types simultaneously. Signed-off-by: Jeff King <peff@peff.net> --- Documentation/git-remote.txt | 19 +++++++--- builtin/remote.c | 51 ++++++++++++++++++++------- t/t5505-remote.sh | 78 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 19 deletions(-) diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 37bd3e5..28724a9 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git remote' [-v | --verbose] -'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror] <name> <url> +'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url> 'git remote rename' <old> <new> 'git remote rm' <name> 'git remote set-head' <name> (-a | -d | <branch>) @@ -67,11 +67,18 @@ multiple branches without grabbing all branches. With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set up to point at remote's `<master>` branch. See also the set-head command. + -In mirror mode, enabled with `\--mirror`, the refs will not be stored -in the 'refs/remotes/' namespace, but in 'refs/heads/'. This option -only makes sense in bare repositories. If a remote uses mirror -mode, furthermore, `git push` will always behave as if `\--mirror` -was passed. +When a fetch mirror is created with `\--mirror=fetch`, the refs will not +be stored in the 'refs/remotes/' namespace, but rather everything in +'refs/' on the remote will be directly mirrored into 'refs/' in the +local repository. This option only makes sense in bare repositories, +because a fetch would overwrite any local commits. ++ +When a push mirror is created with `\--mirror=push`, then `git push` +will always behave as if `\--mirror` was passed. ++ +The option `\--mirror` (with no type) sets up both push and fetch +mirror configuration. It is kept for historical purposes, and is +probably not what you want. 'rename':: diff --git a/builtin/remote.c b/builtin/remote.c index 2e25c6a..570407f 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -9,7 +9,7 @@ static const char * const builtin_remote_usage[] = { "git remote [-v | --verbose]", - "git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>", + "git remote add [-t <branch>] [-m <master>] [-f] [--mirror=<fetch|push>] <name> <url>", "git remote rename <old> <new>", "git remote rm <name>", "git remote set-head <name> (-a | -d | <branch>)", @@ -117,6 +117,11 @@ enum { TAGS_SET = 2 }; +#define MIRROR_NONE 0 +#define MIRROR_FETCH 1 +#define MIRROR_PUSH 2 +#define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH) + static int add_branch(const char *key, const char *branchname, const char *remotename, int mirror, struct strbuf *tmp) { @@ -131,9 +136,26 @@ static int add_branch(const char *key, const char *branchname, return git_config_set_multivar(key, tmp->buf, "^$", 0); } +static int parse_mirror_opt(const struct option *opt, const char *arg, int not) +{ + unsigned *mirror = opt->value; + if (not) + *mirror = MIRROR_NONE; + else if (!arg) + *mirror = MIRROR_BOTH; + else if (!strcmp(arg, "fetch")) + *mirror = MIRROR_FETCH; + else if (!strcmp(arg, "push")) + *mirror = MIRROR_PUSH; + else + return error("unknown mirror argument: %s", arg); + return 0; +} + static int add(int argc, const char **argv) { - int fetch = 0, mirror = 0, fetch_tags = TAGS_DEFAULT; + int fetch = 0, fetch_tags = TAGS_DEFAULT; + unsigned mirror = MIRROR_NONE; struct string_list track = STRING_LIST_INIT_NODUP; const char *master = NULL; struct remote *remote; @@ -151,7 +173,9 @@ static int add(int argc, const char **argv) OPT_CALLBACK('t', "track", &track, "branch", "branch(es) to track", opt_parse_track), OPT_STRING('m', "master", &master, "branch", "master branch"), - OPT_BOOLEAN(0, "mirror", &mirror, "no separate remotes"), + { OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch", + "set up remote as a mirror to push to or fetch from", + PARSE_OPT_OPTARG, parse_mirror_opt }, OPT_END() }; @@ -182,18 +206,19 @@ static int add(int argc, const char **argv) if (git_config_set(buf.buf, url)) return 1; - strbuf_reset(&buf); - strbuf_addf(&buf, "remote.%s.fetch", name); - - if (track.nr == 0) - string_list_append(&track, "*"); - for (i = 0; i < track.nr; i++) { - if (add_branch(buf.buf, track.items[i].string, - name, mirror, &buf2)) - return 1; + if (!mirror || mirror & MIRROR_FETCH) { + strbuf_reset(&buf); + strbuf_addf(&buf, "remote.%s.fetch", name); + if (track.nr == 0) + string_list_append(&track, "*"); + for (i = 0; i < track.nr; i++) { + if (add_branch(buf.buf, track.items[i].string, + name, mirror, &buf2)) + return 1; + } } - if (mirror) { + if (mirror & MIRROR_PUSH) { strbuf_reset(&buf); strbuf_addf(&buf, "remote.%s.mirror", name); if (git_config_set(buf.buf, "true")) diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index d189add..4e69c90 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -304,6 +304,84 @@ test_expect_success 'add --mirror && prune' ' git rev-parse --verify refs/heads/side) ' +test_expect_success 'add --mirror=fetch' ' + mkdir mirror-fetch && + git init mirror-fetch/parent && + (cd mirror-fetch/parent && + test_commit one) && + git init --bare mirror-fetch/child && + (cd mirror-fetch/child && + git remote add --mirror=fetch -f parent ../parent) +' + +test_expect_success 'fetch mirrors act as mirrors during fetch' ' + (cd mirror-fetch/parent && + git branch new && + git branch -m master renamed + ) && + (cd mirror-fetch/child && + git fetch parent && + git rev-parse --verify refs/heads/new && + git rev-parse --verify refs/heads/renamed + ) +' + +test_expect_success 'fetch mirrors can prune' ' + (cd mirror-fetch/child && + git remote prune parent && + test_must_fail git rev-parse --verify refs/heads/master + ) +' + +test_expect_success 'fetch mirrors do not act as mirrors during push' ' + (cd mirror-fetch/parent && + git checkout HEAD^0 + ) && + (cd mirror-fetch/child && + git branch -m renamed renamed2 && + git push parent + ) && + (cd mirror-fetch/parent && + git rev-parse --verify renamed && + test_must_fail git rev-parse --verify refs/heads/renamed2 + ) +' + +test_expect_success 'add --mirror=push' ' + mkdir mirror-push && + git init --bare mirror-push/public && + git init mirror-push/private && + (cd mirror-push/private && + test_commit one && + git remote add --mirror=push public ../public + ) +' + +test_expect_success 'push mirrors act as mirrors during push' ' + (cd mirror-push/private && + git branch new && + git branch -m master renamed && + git push public + ) && + (cd mirror-push/private && + git rev-parse --verify refs/heads/new && + git rev-parse --verify refs/heads/renamed && + test_must_fail git rev-parse --verify refs/heads/master + ) +' + +test_expect_success 'push mirrors do not act as mirrors during fetch' ' + (cd mirror-push/public && + git branch -m renamed renamed2 && + git symbolic-ref HEAD refs/heads/renamed2 + ) && + (cd mirror-push/private && + git fetch public && + git rev-parse --verify refs/heads/renamed && + test_must_fail git rev-parse --verify refs/heads/renamed2 + ) +' + test_expect_success 'add alt && prune' ' (mkdir alttst && cd alttst && -- 1.7.4.2.8.g3ccd6 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-30 19:53 ` [PATCH 2/3] remote: separate the concept of push and fetch mirrors Jeff King @ 2011-03-30 20:45 ` Junio C Hamano 2011-03-30 20:57 ` Jeff King 0 siblings, 1 reply; 13+ messages in thread From: Junio C Hamano @ 2011-03-30 20:45 UTC (permalink / raw) To: Jeff King; +Cc: chris, Jan Hudec, git Jeff King <peff@peff.net> writes: > git-remote currently has one option, "--mirror", which sets > up mirror configuration which can be used for either > fetching or pushing. It looks like this: > > [remote "mirror"] > url = wherever > fetch = +refs/*:refs/* > mirror = true > > However, a remote like this can be dangerous and confusing. When --mirror was introduced at 3894439 (Teach "git remote" a mirror mode, 2007-09-02), it was only about fetching into a bare repository from another repository and there wasn't any confusion. I knew about this potential confusion when we applied 84bb2df (Add a remote.*.mirror configuration option, 2008-04-17), but chose to be lazy and ignored the issue, thinking that users are intelligent enough not to mix these obviously incompatible modes of operation. If a repository is a mirror to fetch from somebody else, you wouldn't develop in it in the first place, and you would definitely not push it back to where you are mirroring from. If a repository is mirrored into somewhere else to publish your work in there, you wouldn't be fetching back from there to obliterate your work. Being explicit like your series does is much safer than relying on "common sense". I briefly wondered if this affects one use case where you want to configure a bare repository at your firewall boundary as a relay that mirrors an external public repository of somebody else by fetching and then publishes that to a repository internal to your network by pushing, but in that case you would have two remotes (the external --mirror=fetch one, and the internal --mirror=push one) that are separate, so it is not an issue. Thanks for cleaning up the two-year old mess. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-30 20:45 ` Junio C Hamano @ 2011-03-30 20:57 ` Jeff King 2011-03-30 22:22 ` Junio C Hamano 0 siblings, 1 reply; 13+ messages in thread From: Jeff King @ 2011-03-30 20:57 UTC (permalink / raw) To: Junio C Hamano; +Cc: chris, Jan Hudec, git On Wed, Mar 30, 2011 at 01:45:59PM -0700, Junio C Hamano wrote: > Jeff King <peff@peff.net> writes: > > > git-remote currently has one option, "--mirror", which sets > > up mirror configuration which can be used for either > > fetching or pushing. It looks like this: > > > > [remote "mirror"] > > url = wherever > > fetch = +refs/*:refs/* > > mirror = true > > > > However, a remote like this can be dangerous and confusing. > > When --mirror was introduced at 3894439 (Teach "git remote" a mirror mode, > 2007-09-02), it was only about fetching into a bare repository from > another repository and there wasn't any confusion. > > I knew about this potential confusion when we applied 84bb2df (Add a > remote.*.mirror configuration option, 2008-04-17), but chose to be lazy > and ignored the issue, thinking that users are intelligent enough not to > mix these obviously incompatible modes of operation. If a repository is a > mirror to fetch from somebody else, you wouldn't develop in it in the > first place, and you would definitely not push it back to where you are > mirroring from. If a repository is mirrored into somewhere else to > publish your work in there, you wouldn't be fetching back from there to > obliterate your work. > > Being explicit like your series does is much safer than relying on "common > sense". I think the problem is not that users lack common sense. It is that we give them an option called "--mirror" that sets up a bogus config in some circumstances. So it is the git developers who lack common sense, I think. :) Specifically, 84bb2df should not have started setting "remote.*.mirror", as it was already about fetching into a bare repository. And probably --mirror in a non-bare repo should have complained from the beginning. But hey, hindsight is 20/20. > I briefly wondered if this affects one use case where you want to > configure a bare repository at your firewall boundary as a relay that > mirrors an external public repository of somebody else by fetching and > then publishes that to a repository internal to your network by pushing, > but in that case you would have two remotes (the external --mirror=fetch > one, and the internal --mirror=push one) that are separate, so it is not > an issue. Exactly. I almost said in the commit message for 3/3 that you would never ever want to have both remote.*.mirror set to true _and_ have remote.*.fetch set to "+refs/*:refs/*". Because by deprecating --mirror, we are saying that situation is not useful. But I really don't think it is. The only instance I could think of would be a case where you have two backup repos, and you might sometimes mirror in one direction and sometimes in the other depending on some external factors (e.g., which one you were last able to connect to from some third repo). But even then, I think I would use two separate repos. Not to mention that "git remote" is supposed to be a friendly helper. If you want to do something crazy, you're welcome to "git config" it yourself. :) > Thanks for cleaning up the two-year old mess. No problem. Two complaints in recent memory triggered my "OK, I guess this is biting people" instinct. :) -Peff ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-30 20:57 ` Jeff King @ 2011-03-30 22:22 ` Junio C Hamano 2011-03-31 2:44 ` chris 0 siblings, 1 reply; 13+ messages in thread From: Junio C Hamano @ 2011-03-30 22:22 UTC (permalink / raw) To: Jeff King; +Cc: chris, Jan Hudec, git Jeff King <peff@peff.net> writes: > I think the problem is not that users lack common sense. It is that we > give them an option called "--mirror" that sets up a bogus config in > some circumstances. So it is the git developers who lack common sense, I > think. :) > > Specifically, 84bb2df should not have started setting "remote.*.mirror", > as it was already about fetching into a bare repository. And probably > --mirror in a non-bare repo should have complained from the beginning. What I meant was that what 84bb2df did was sufficient for people who know which one they wanted and stuck with what they said they wanted. What would we call a person who first asks "I want a push mirror to save away my work" and then says "now let's fetch from there", without realizing that such a fetch will obliterate his work? I agree that it probably is asking a bit more than "common sense"; it perhaps requires an ability to think for 5 minutes what oneself is doing ;-). > But hey, hindsight is 20/20. Indeed. Thanks. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-30 22:22 ` Junio C Hamano @ 2011-03-31 2:44 ` chris 2011-03-31 2:50 ` chris 0 siblings, 1 reply; 13+ messages in thread From: chris @ 2011-03-31 2:44 UTC (permalink / raw) To: git Junio C Hamano <gitster <at> pobox.com> writes: > > What would we call a person who first asks "I want a push mirror to save > away my work" and then says "now let's fetch from there", without > realizing that such a fetch will obliterate his work? I agree that it > probably is asking a bit more than "common sense"; it perhaps requires an > ability to think for 5 minutes what oneself is doing . If I have to stop and think for 5 minutes before I execute any git command, I think there may be an issue with the tool. :) That said - the above thoughts were never the source of my surprise. The only surprising aspect of this whole thing was the behavior of branch.autosetupmerge when a 'mirror' remote existed. Essentially the existence of the mirror remote turned all local branches into remote-tracking branches - that is surprising. I have no issue with --mirror having its current behavior (although the proposed changes certainly are more explicit and therefore clearer), however, I propose that branch.autosetupmerge should ignore remotes with mirror = true. I'd also propose that when setting up a --mirror, if the repository is not bare, that the fetch refs be set to "refs/*:refs/*" rather than "+refs/*:refs/*". With those two changes, I get the functionality I want without surprises. I use the mirror for synchronizing "local" work between my workstations (home/office). So, I use the fact that I can fetch and pull from the mirror. chris ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-31 2:44 ` chris @ 2011-03-31 2:50 ` chris 2011-03-31 4:03 ` Junio C Hamano 0 siblings, 1 reply; 13+ messages in thread From: chris @ 2011-03-31 2:50 UTC (permalink / raw) To: git chris <jugg <at> hotmail.com> writes: > > I use the mirror for synchronizing "local" work between my workstations > (home/office). So, I use the fact that I can fetch and pull from the mirror. That of course should say: So, I use the fact that I can fetch from and *push* to the mirror. chris ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-31 2:50 ` chris @ 2011-03-31 4:03 ` Junio C Hamano 2011-03-31 12:59 ` chris 0 siblings, 1 reply; 13+ messages in thread From: Junio C Hamano @ 2011-03-31 4:03 UTC (permalink / raw) To: chris; +Cc: git chris <jugg@hotmail.com> writes: >> I use the mirror for synchronizing "local" work between my workstations >> (home/office). So, I use the fact that I can fetch and pull from the mirror. > > That of course should say: > > So, I use the fact that I can fetch from and *push* to the mirror. It is not quite clear what you meant by "mirror" above, but I am assuming that you meant that you have a third repository that you use for the sole purpose of synchronizing your work done in two repositories, one at home and the other at office. The synchronizing point should be a normal remote in such a case. If you mirror-push into the mirror from home, you may lose what you have pushed from office that you forgot to pull back to home before starting to work at home via the mirror. If you mirror-fetch from the mirror from office, you may lose what you worked locally on office and forgot to push out before mirror-fetching for one thing, and for another, you will be overwriting the tip of your current branch. Using a pure mirror in such a three-repository situation _can_ be made to work, but only if you are very careful: before you leave home, commit everything and push to the mirror and then go to office; when you come to the office, fetch from the mirror and "reset --hard" before doing anything else; before leaving office, commit everything and push to the mirror; when you come home, fetch from the mirror and "reset --hard" before doing anything. Ad infinitum... Hopefully we are already forbidding mirror fetching into a non-bare repository, so the system is foolproofed in that direction at least to avoid such mistakes. I offhand do not remember if we protect the branch that is currently checked out from mirror pushing, though. Hopefully, receive.denycurrentbranch will protect it, but other branches may happily get rewound when you do a mirror push. A safer and more customary way to set up the synchronization between two repositories is to arrange them to pull from each other (and if you can initiate connections only in one direction, emulate one side of "git fetch" with "git push"). In such an arrangement, a local branch "master" at home will correspond to "refs/remotes/home/master" at the office, and a local branch "master" at the office will correspond to "refs/remotes/office/master" at home. There is no mirror configuration involved. Hopefully this will clear things up somewhat. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] remote: separate the concept of push and fetch mirrors 2011-03-31 4:03 ` Junio C Hamano @ 2011-03-31 12:59 ` chris 0 siblings, 0 replies; 13+ messages in thread From: chris @ 2011-03-31 12:59 UTC (permalink / raw) To: git Junio C Hamano <gitster <at> pobox.com> writes: > > chris <jugg <at> hotmail.com> writes: > > >> I use the mirror for synchronizing "local" work between my workstations > >> (home/office). So, I use the fact that I can fetch from and push to the mirror. > > It is not quite clear what you meant by "mirror" above, but I am assuming > that you meant that you have a third repository that you use for the sole > purpose of synchronizing your work done in two repositories, one at home > and the other at office. Yes, I was referencing my original post from the top level thread that triggered these patches. > The synchronizing point should be a normal remote in such a case. I find that much more cumbersome. It is much simpler for me to generate various patch branches and before calling it a day/night put all of my pending changes into a wip branch that isn't already on another branch and push to my mirror remote - all refs are pushed. No need to concern myself with ensuring I don't forget a newly created local ref. > If you > mirror-push into the mirror from home, you may lose what you have pushed > from office that you forgot to pull back to home before starting to work > at home via the mirror. It is much more likely for me to forget to push a local ref than to forget to synchronize - the point of this activity is to continue my work in a different location, something I couldn't do if I don't synchronize. As for content in the mirror itself being lost - that is irrelevant, it is just a buffer. The home and/or work repositories have whatever is in the mirror - fetching from the mirror is where fail safes, if any, are needed. > If you mirror-fetch from the mirror from office, > you may lose what you worked locally on office and forgot to push out > before mirror-fetching for one thing, and for another, you will be > overwriting the tip of your current branch. yes, which is the point of my second suggestion to change the fetch refs for a mirror remote if the local repository is not bare. But generally, when intentionally fetching from a mirror I want it to overwrite whatever I have locally, probably because I *had* forgotten to push from home the night before, and subsequently re-implemented the work at the office, so when I get home the following night, I just blow away whatever I have locally with my work from the office. But that action certainly should be explicitly requested and not the default. > Using a pure mirror in such a three-repository situation _can_ be made to > work, but only if you are very careful: *careful* depends on work flow. And a pure mirror approach works quite well for me in this situation, with less effort than manually managing what refs to push. > Hopefully we are already forbidding mirror fetching into a non-bare > repository, so the system is foolproofed in that direction at least to > avoid such mistakes. If you mean what I think you mean, then you are not. > I offhand do not remember if we protect the branch > that is currently checked out from mirror pushing, though. I don't know - I've only mirror pushed to a bare repository. > A safer and more customary way to set up the synchronization between two > repositories is to arrange them to pull from each other (and if you can > initiate connections only in one direction, emulate one side of "git > fetch" with "git push"). "customary" or "ideal"? I certainly won't argue the convenience of such a setup if the logistics allowed for it. Of course the most ideal way to solve this problem would be to have a laptop. In the mean time I have a really useful tool called Git that generally has just enough rounded edges to avoid stabbing myself, but does not dumb things down to the point of being controlling. :) chris ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/3] remote: deprecate --mirror 2011-03-30 19:51 ` [PATCH 0/3] better "remote add --mirror" semantics Jeff King 2011-03-30 19:52 ` [PATCH 1/3] remote: disallow some nonsensical option combinations Jeff King 2011-03-30 19:53 ` [PATCH 2/3] remote: separate the concept of push and fetch mirrors Jeff King @ 2011-03-30 19:53 ` Jeff King 2 siblings, 0 replies; 13+ messages in thread From: Jeff King @ 2011-03-30 19:53 UTC (permalink / raw) To: chris; +Cc: Jan Hudec, git The configuration created by plain --mirror is dangerous and useless, and we now have --mirror=fetch and --mirror=push to replace it. Let's warn the user. One alternative to this is to try to guess which type the user wants. In a non-bare repository, a fetch mirror doesn't make much sense, since it would overwrite local commits. But in a bare repository, you might use either type, or even both (e.g., if you are acting as an intermediate drop-point across two disconnected networks). So rather than try for complex heuristics, let's keep it simple. The user knows what they're trying to do, so let them tell us. Signed-off-by: Jeff King <peff@peff.net> --- Documentation/git-remote.txt | 4 ---- builtin/remote.c | 8 +++++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 28724a9..528f34a 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -75,10 +75,6 @@ because a fetch would overwrite any local commits. + When a push mirror is created with `\--mirror=push`, then `git push` will always behave as if `\--mirror` was passed. -+ -The option `\--mirror` (with no type) sets up both push and fetch -mirror configuration. It is kept for historical purposes, and is -probably not what you want. 'rename':: diff --git a/builtin/remote.c b/builtin/remote.c index 570407f..8424152 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -136,13 +136,19 @@ static int add_branch(const char *key, const char *branchname, return git_config_set_multivar(key, tmp->buf, "^$", 0); } +static const char mirror_advice[] = +"--mirror is dangerous and deprecated; please\n" +"\t use --mirror=fetch or --mirror=push instead"; + static int parse_mirror_opt(const struct option *opt, const char *arg, int not) { unsigned *mirror = opt->value; if (not) *mirror = MIRROR_NONE; - else if (!arg) + else if (!arg) { + warning("%s", mirror_advice); *mirror = MIRROR_BOTH; + } else if (!strcmp(arg, "fetch")) *mirror = MIRROR_FETCH; else if (!strcmp(arg, "push")) -- 1.7.4.2.8.g3ccd6 ^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2011-03-31 13:00 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-03-30 2:27 checkout new branch tracks wrong remote (bug?) chris 2011-03-30 14:59 ` Jeff King 2011-03-30 19:51 ` [PATCH 0/3] better "remote add --mirror" semantics Jeff King 2011-03-30 19:52 ` [PATCH 1/3] remote: disallow some nonsensical option combinations Jeff King 2011-03-30 19:53 ` [PATCH 2/3] remote: separate the concept of push and fetch mirrors Jeff King 2011-03-30 20:45 ` Junio C Hamano 2011-03-30 20:57 ` Jeff King 2011-03-30 22:22 ` Junio C Hamano 2011-03-31 2:44 ` chris 2011-03-31 2:50 ` chris 2011-03-31 4:03 ` Junio C Hamano 2011-03-31 12:59 ` chris 2011-03-30 19:53 ` [PATCH 3/3] remote: deprecate --mirror Jeff King
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).