git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 3/6] push: change `simple` to accommodate triangular workflows

From
Johan Herland <johan@herland.net>
Date
Jun 24, 2013, 06:58 UTC
Message-ID
<CALKQrgfAT9GhD-_tZHr9wRA6R6g7ttDWTsmUQXdWUhG-gwNBqQ@mail.gmail.com>
In-Reply-To
<1372048388-16742-4-git-send-email-gitster@pobox.com>
On Mon, Jun 24, 2013 at 6:33 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 26 quoted lines
> From: Ramkumar Ramachandra <artagnon@gmail.com>
>
> When remote.pushdefault or branch.<name>.pushremote is set (a triangular
> workflow feature), master@{u} != origin, and push.default is set to
> `upstream` or `simple`:
>
>   $ git push
>   fatal: You are pushing to remote 'origin', which is not the upstream of
>   your current branch 'master', without telling me what to push
>   to update which remote branch.
>
> The very name of "upstream" indicates that it is only suitable for
> use in central workflows; let us not even attempt to give it a new
> meaning in triangular workflows, and error out as usual.
>
> However, the `simple` does not have this problem: it is poised to be
> the default for Git 2.0, and we would definitely like it to do
> something sensible in triangular workflows.
>
> Redefine "simple" as "safer upstream" for centralized workflow as
> before, but work as "current" for triangular workflow.
>
> An earlier round of this change by mistake broke the safety for
> "simple" mode we have had since day 1 of that mode to make sure that
> the branch in the repository we update is set to be the one we fetch
> and integrate with, but it has been fixed.
Shouldn't there be an acompanying test to demonstrate this mistake being fixed?
Show 75 quoted lines
> Reported-by: Leandro Lucarella <leandro.lucarella@sociomantic.com>
> Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  Documentation/config.txt | 10 +++++++---
>  builtin/push.c           | 43 +++++++++++++++++++++++++++++++------------
>  2 files changed, 38 insertions(+), 15 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 5d8ff1a..cae6870 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -1848,9 +1848,13 @@ push.default::
>    pushing to the same repository you would normally pull from
>    (i.e. central workflow).
>
> -* `simple` - like `upstream`, but refuses to push if the upstream
> -  branch's name is different from the local one. This is the safest
> -  option and is well-suited for beginners.
> +* `simple` - in centralized workflow, work like `upstream` with an
> +  added safety to refuse to push if the upstream branch's name is
> +  different from the local one.
> ++
> +When pushing to a remote that is different from the remote you normally
> +pull from, work as `current`.  This is the safest option and is suited
> +for beginners.
>  +
>  This mode will become the default in Git 2.0.
>
> diff --git a/builtin/push.c b/builtin/push.c
> index 2d84d10..f6c8047 100644
> --- a/builtin/push.c
> +++ b/builtin/push.c
> @@ -120,10 +120,11 @@ static const char message_detached_head_die[] =
>            "\n"
>            "    git push %s HEAD:<name-of-remote-branch>\n");
>
> -static void setup_push_upstream(struct remote *remote, int simple)
> +static void setup_push_upstream(struct remote *remote, struct branch *branch,
> +                               int triangular)
>  {
>         struct strbuf refspec = STRBUF_INIT;
> -       struct branch *branch = branch_get(NULL);
> +
>         if (!branch)
>                 die(_(message_detached_head_die), remote->name);
>         if (!branch->merge_nr || !branch->merge || !branch->remote_name)
> @@ -137,18 +138,29 @@ static void setup_push_upstream(struct remote *remote, int simple)
>         if (branch->merge_nr != 1)
>                 die(_("The current branch %s has multiple upstream branches, "
>                     "refusing to push."), branch->name);
> -       if (strcmp(branch->remote_name, remote->name))
> +       if (triangular)
>                 die(_("You are pushing to remote '%s', which is not the upstream of\n"
>                       "your current branch '%s', without telling me what to push\n"
>                       "to update which remote branch."),
>                     remote->name, branch->name);
> -       if (simple && strcmp(branch->refname, branch->merge[0]->src))
> -               die_push_simple(branch, remote);
> +
> +       if (push_default == PUSH_DEFAULT_SIMPLE) {
> +               /* Additional safety */
> +               if (strcmp(branch->refname, branch->merge[0]->src))
> +                       die_push_simple(branch, remote);
> +       }
>
>         strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
>         add_refspec(refspec.buf);
>  }
>
> +static void setup_push_current(struct remote *remote, struct branch *branch)
> +{
> +       if (!branch)
> +               die(_(message_detached_head_die), remote->name);
> +       add_refspec(branch->name);

Here (and above) we add a refspec to tell Git exactly what to push from the local end, and into what on the remote end. Is it possible to end up with multiple simultaneous refspecs matching the same local ref, but mapping to different remote refs? If so, which will win, and does that make sense?

Show 10 quoted lines
> +}
> +
>  static char warn_unspecified_push_default_msg[] =
>  N_("push.default is unset; its implicit value is changing in\n"
>     "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
> @@ -173,9 +185,16 @@ static void warn_unspecified_push_default_configuration(void)
>         warning("%s\n", _(warn_unspecified_push_default_msg));
>  }
>
> +static int is_workflow_triagular(struct remote *remote)
s/triagular/triangular/
> +{
> +       struct remote *fetch_remote = remote_get(NULL);
> +       return (fetch_remote && fetch_remote != remote);

This changed from a strcmp() to a pointer compare. That might be safe, depending on the sources of the two struct remote *, but I'm not sure.

Show 35 quoted lines
> +}
> +
>  static void setup_default_push_refspecs(struct remote *remote)
>  {
> -       struct branch *branch;
> +       struct branch *branch = branch_get(NULL);
> +       int triangular = is_workflow_triagular(remote);
>
>         switch (push_default) {
>         default:
> @@ -188,18 +207,18 @@ static void setup_default_push_refspecs(struct remote *remote)
>                 break;
>
>         case PUSH_DEFAULT_SIMPLE:
> -               setup_push_upstream(remote, 1);
> +               if (triangular)
> +                       setup_push_current(remote, branch);
> +               else
> +                       setup_push_upstream(remote, branch, triangular);
>                 break;
>
>         case PUSH_DEFAULT_UPSTREAM:
> -               setup_push_upstream(remote, 0);
> +               setup_push_upstream(remote, branch, triangular);
>                 break;
>
>         case PUSH_DEFAULT_CURRENT:
> -               branch = branch_get(NULL);
> -               if (!branch)
> -                       die(_(message_detached_head_die), remote->name);
> -               add_refspec(branch->name);
> +               setup_push_current(remote, branch);
>                 break;
>
>         case PUSH_DEFAULT_NOTHING:
Otherwise, this looks good to me.
...Johan
-- 
Johan Herland, <johan@herland.net>
www.herland.net
Previous: Junio C HamanoNext: Junio C Hamano
Message 5 of 36 in “Reroll of rr/triangular-push-fix”
  1. 0/6 Reroll of rr/triangular-push-fixJunio C Hamano, Jun 24, 2013
  2. 1/6 t/t5528-push-default: remove redundant test_config linesJunio C Hamano, Jun 24, 2013
  3. 2/6 config doc: rewrite push.default sectionJunio C Hamano, Jun 24, 2013
  4. 3/6 push: change `simple` to accommodate triangular workflowsJunio C Hamano, Jun 24, 2013
  5. Johan HerlandJun 24, 2013
  6. Junio C HamanoJun 24, 2013
  7. Ramkumar RamachandraJun 24, 2013
  8. Johan HerlandJun 24, 2013
  9. Ramkumar RamachandraJun 24, 2013
  10. Junio C HamanoJun 24, 2013
  11. Johan HerlandJun 24, 2013
  12. 4/6 t/t5528-push-default: generalize test_push_*Junio C Hamano, Jun 24, 2013
  13. Johan HerlandJun 24, 2013
  14. Junio C HamanoJun 24, 2013
  15. Johan HerlandJun 24, 2013
  16. Eric SunshineJun 24, 2013
  17. Johan HerlandJun 24, 2013
  18. Junio C HamanoJun 24, 2013
  19. 5/6 t/t5528-push-default: test pushdefault workflowsJunio C Hamano, Jun 24, 2013
  20. 6/6 push: honor branch.*.pushJunio C Hamano, Jun 24, 2013
  21. Johan HerlandJun 24, 2013
  22. Junio C HamanoJun 24, 2013
  23. Ramkumar RamachandraJun 24, 2013
  24. Junio C HamanoJun 24, 2013
  25. Ramkumar RamachandraJun 24, 2013
  26. Johan HerlandJun 24, 2013
  27. Junio C HamanoJun 24, 2013
  28. Junio C HamanoJun 24, 2013
  29. Ramkumar RamachandraJun 24, 2013
  30. Junio C HamanoJun 24, 2013
  31. Ramkumar RamachandraJun 24, 2013
  32. Junio C HamanoJun 24, 2013
  33. Ramkumar RamachandraJun 24, 2013
  34. Ramkumar RamachandraJun 24, 2013
  35. Junio C HamanoJun 24, 2013
  36. Ramkumar RamachandraJun 24, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.