Code

Merge branch 'pj/remote-set-branches-usage-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 23 Feb 2012 21:30:00 +0000 (13:30 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 23 Feb 2012 21:30:00 +0000 (13:30 -0800)
* pj/remote-set-branches-usage-fix:
  remote: fix set-branches usage and documentation

Conflicts:
builtin/remote.c

1  2 
Documentation/git-remote.txt
builtin/remote.c

index 5a8c5061f3701c57bab75b2b4c70ad620f7e536f,7112f94000d2a9e9ed69eaa5d699633d5c95117e..d376d19ef79962c5755e958eec7a491c96479a1f
@@@ -10,17 -10,17 +10,17 @@@ SYNOPSI
  --------
  [verse]
  'git remote' [-v | --verbose]
 -'git remote add' [-t <branch>] [-m <master>] [-f] [--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>)
- 'git remote set-branches' <name> [--add] <branch>...
+ 'git remote set-branches' [--add] <name> <branch>...
  'git remote set-url' [--push] <name> <newurl> [<oldurl>]
  'git remote set-url --add' [--push] <name> <newurl>
  'git remote set-url --delete' [--push] <name> <url>
  'git remote' [-v | --verbose] 'show' [-n] <name>
  'git remote prune' [-n | --dry-run] <name>
 -'git remote' [-v | --verbose] 'update' [-p | --prune] [group | remote]...
 +'git remote' [-v | --verbose] 'update' [-p | --prune] [(<group> | <remote>)...]
  
  DESCRIPTION
  -----------
@@@ -52,33 -52,24 +52,33 @@@ update remote-tracking branches <name>/
  With `-f` option, `git fetch <name>` is run immediately after
  the remote information is set up.
  +
 +With `--tags` option, `git fetch <name>` imports every tag from the
 +remote repository.
 ++
 +With `--no-tags` option, `git fetch <name>` does not import tags from
 +the remote repository.
 ++
  With `-t <branch>` option, instead of the default glob
  refspec for the remote to track all branches under
 -`$GIT_DIR/remotes/<name>/`, a refspec to track only `<branch>`
 +the `refs/remotes/<name>/` namespace, a refspec to track only `<branch>`
  is created.  You can give more than one `-t <branch>` to track
  multiple branches without grabbing all branches.
  +
 -With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
 +With `-m <master>` option, a symbolic-ref `refs/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.
  
  'rename'::
  
 -Rename the remote named <old> to <new>. All remote tracking branches and
 +Rename the remote named <old> to <new>. All remote-tracking branches and
  configuration settings for the remote are updated.
  +
  In case <old> and <new> are the same, and <old> is a file under
@@@ -87,30 -78,29 +87,30 @@@ the configuration file format
  
  'rm'::
  
 -Remove the remote named <name>. All remote tracking branches and
 +Remove the remote named <name>. All remote-tracking branches and
  configuration settings for the remote are removed.
  
  'set-head'::
  
 -Sets or deletes the default branch (`$GIT_DIR/remotes/<name>/HEAD`) for
 +Sets or deletes the default branch (i.e. the target of the
 +symbolic-ref `refs/remotes/<name>/HEAD`) for
  the named remote. Having a default branch for a remote is not required,
  but allows the name of the remote to be specified in lieu of a specific
  branch. For example, if the default branch for `origin` is set to
  `master`, then `origin` may be specified wherever you would normally
  specify `origin/master`.
  +
 -With `-d`, `$GIT_DIR/remotes/<name>/HEAD` is deleted.
 +With `-d`, the symbolic ref `refs/remotes/<name>/HEAD` is deleted.
  +
 -With `-a`, the remote is queried to determine its `HEAD`, then
 -`$GIT_DIR/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote
 +With `-a`, the remote is queried to determine its `HEAD`, then the
 +symbolic-ref `refs/remotes/<name>/HEAD` is set to the same branch. e.g., if the remote
  `HEAD` is pointed at `next`, "`git remote set-head origin -a`" will set
 -`$GIT_DIR/refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will
 +the symbolic-ref `refs/remotes/origin/HEAD` to `refs/remotes/origin/next`. This will
  only work if `refs/remotes/origin/next` already exists; if not it must be
  fetched first.
  +
 -Use `<branch>` to set `$GIT_DIR/remotes/<name>/HEAD` explicitly. e.g., "git
 -remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to
 +Use `<branch>` to set the symbolic-ref `refs/remotes/<name>/HEAD` explicitly. e.g., "git
 +remote set-head origin master" will set the symbolic-ref `refs/remotes/origin/HEAD` to
  `refs/remotes/origin/master`. This will only work if
  `refs/remotes/origin/master` already exists; if not it must be fetched first.
  +
@@@ -150,7 -140,7 +150,7 @@@ With `-n` option, the remote heads are 
  
  'prune'::
  
 -Deletes all stale tracking branches under <name>.
 +Deletes all stale remote-tracking branches under <name>.
  These stale branches have already been removed from the remote repository
  referenced by <name>, but are still locally available in
  "remotes/<name>".
@@@ -218,6 -208,16 +218,6 @@@ linkgit:git-fetch[1
  linkgit:git-branch[1]
  linkgit:git-config[1]
  
 -Author
 -------
 -Written by Junio Hamano
 -
 -
 -Documentation
 ---------------
 -Documentation by J. Bruce Fields and the git-list <git@vger.kernel.org>.
 -
 -
  GIT
  ---
  Part of the linkgit:git[1] suite
diff --combined builtin/remote.c
index f54a89adc795fe86f76d60cff4de9487bc792bd3,7f3514b7087cb92bb54278cbc1fffdb0881d41b8..fec92bc66e41b82f929e37b1935d00d6558c34a0
@@@ -1,4 -1,4 +1,4 @@@
 -#include "cache.h"
 +#include "builtin.h"
  #include "parse-options.h"
  #include "transport.h"
  #include "remote.h"
@@@ -9,14 -9,14 +9,14 @@@
  
  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>)",
        "git remote [-v | --verbose] show [-n] <name>",
        "git remote prune [-n | --dry-run] <name>",
 -      "git remote [-v | --verbose] update [-p | --prune] [group | remote]",
 +      "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]",
-       "git remote set-branches <name> [--add] <branch>...",
+       "git remote set-branches [--add] <name> <branch>...",
        "git remote set-url <name> <newurl> [<oldurl>]",
        "git remote set-url --add <name> <newurl>",
        "git remote set-url --delete <name> <url>",
@@@ -88,6 -88,16 +88,6 @@@ static inline int postfixcmp(const cha
        return strcmp(string + len1 - len2, postfix);
  }
  
 -static int opt_parse_track(const struct option *opt, const char *arg, int not)
 -{
 -      struct string_list *list = opt->value;
 -      if (not)
 -              string_list_clear(list, 0);
 -      else
 -              string_list_append(arg, list);
 -      return 0;
 -}
 -
  static int fetch_remote(const char *name)
  {
        const char *argv[] = { "fetch", name, NULL, NULL };
        return 0;
  }
  
 +enum {
 +      TAGS_UNSET = 0,
 +      TAGS_DEFAULT = 1,
 +      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)
  {
        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) {
 +              warning("%s", mirror_advice);
 +              *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;
 -      struct string_list track = { NULL, 0, 0 };
 +      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;
        struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
  
        struct option options[] = {
                OPT_BOOLEAN('f', "fetch", &fetch, "fetch the remote branches"),
 -              OPT_CALLBACK('t', "track", &track, "branch",
 -                      "branch(es) to track", opt_parse_track),
 +              OPT_SET_INT(0, "tags", &fetch_tags,
 +                          "import all tags and associated objects when fetching",
 +                          TAGS_SET),
 +              OPT_SET_INT(0, NULL, &fetch_tags,
 +                          "or do not fetch any tag at all (--no-tags)", TAGS_UNSET),
 +              OPT_STRING_LIST('t', "track", &track, "branch",
 +                              "branch(es) to 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()
        };
  
        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 && !(mirror & MIRROR_FETCH) && track.nr)
 +              die("specifying branches to track makes sense only with fetch mirrors");
 +
        name = argv[0];
        url = argv[1];
  
        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"))
                        return 1;
        }
  
 +      if (fetch_tags != TAGS_DEFAULT) {
 +              strbuf_reset(&buf);
 +              strbuf_addf(&buf, "remote.%s.tagopt", name);
 +              if (git_config_set(buf.buf,
 +                      fetch_tags == TAGS_SET ? "--tags" : "--no-tags"))
 +                      return 1;
 +      }
 +
        if (fetch && fetch_remote(name))
                return 1;
  
@@@ -289,7 -244,7 +289,7 @@@ static int config_read_branches(const c
                } else
                        return 0;
  
 -              item = string_list_insert(name, &branch_list);
 +              item = string_list_insert(&branch_list, name);
  
                if (!item->util)
                        item->util = xcalloc(sizeof(struct branch_info), 1);
                        while (space) {
                                char *merge;
                                merge = xstrndup(value, space - value);
 -                              string_list_append(merge, &info->merge);
 +                              string_list_append(&info->merge, merge);
                                value = abbrev_branch(space + 1);
                                space = strchr(value, ' ');
                        }
 -                      string_list_append(xstrdup(value), &info->merge);
 +                      string_list_append(&info->merge, xstrdup(value));
                } else
                        info->rebase = git_config_bool(orig_key, value);
        }
@@@ -343,16 -298,16 +343,16 @@@ static int get_ref_states(const struct 
        states->tracked.strdup_strings = 1;
        states->stale.strdup_strings = 1;
        for (ref = fetch_map; ref; ref = ref->next) {
 -              unsigned char sha1[20];
 -              if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))
 -                      string_list_append(abbrev_branch(ref->name), &states->new);
 +              if (!ref->peer_ref || !ref_exists(ref->peer_ref->name))
 +                      string_list_append(&states->new, abbrev_branch(ref->name));
                else
 -                      string_list_append(abbrev_branch(ref->name), &states->tracked);
 +                      string_list_append(&states->tracked, abbrev_branch(ref->name));
        }
 -      stale_refs = get_stale_heads(states->remote, fetch_map);
 +      stale_refs = get_stale_heads(states->remote->fetch,
 +                                   states->remote->fetch_refspec_nr, fetch_map);
        for (ref = stale_refs; ref; ref = ref->next) {
                struct string_list_item *item =
 -                      string_list_append(abbrev_branch(ref->name), &states->stale);
 +                      string_list_append(&states->stale, abbrev_branch(ref->name));
                item->util = xstrdup(ref->name);
        }
        free_refs(stale_refs);
@@@ -374,7 -329,7 +374,7 @@@ struct push_info 
                PUSH_STATUS_UPTODATE,
                PUSH_STATUS_FASTFORWARD,
                PUSH_STATUS_OUTOFDATE,
 -              PUSH_STATUS_NOTQUERIED,
 +              PUSH_STATUS_NOTQUERIED
        } status;
  };
  
@@@ -389,8 -344,8 +389,8 @@@ static int get_push_ref_states(const st
        local_refs = get_local_heads();
        push_map = copy_ref_list(remote_refs);
  
 -      match_refs(local_refs, &push_map, remote->push_refspec_nr,
 -                 remote->push_refspec, MATCH_REFS_NONE);
 +      match_push_refs(local_refs, &push_map, remote->push_refspec_nr,
 +                      remote->push_refspec, MATCH_REFS_NONE);
  
        states->push.strdup_strings = 1;
        for (ref = push_map; ref; ref = ref->next) {
                        continue;
                hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
  
 -              item = string_list_append(abbrev_branch(ref->peer_ref->name),
 -                                        &states->push);
 +              item = string_list_append(&states->push,
 +                                        abbrev_branch(ref->peer_ref->name));
                item->util = xcalloc(sizeof(struct push_info), 1);
                info = item->util;
                info->forced = ref->force;
@@@ -437,7 -392,7 +437,7 @@@ static int get_push_ref_states_noquery(
  
        states->push.strdup_strings = 1;
        if (!remote->push_refspec_nr) {
 -              item = string_list_append("(matching)", &states->push);
 +              item = string_list_append(&states->push, "(matching)");
                info = item->util = xcalloc(sizeof(struct push_info), 1);
                info->status = PUSH_STATUS_NOTQUERIED;
                info->dest = xstrdup(item->string);
        for (i = 0; i < remote->push_refspec_nr; i++) {
                struct refspec *spec = remote->push + i;
                if (spec->matching)
 -                      item = string_list_append("(matching)", &states->push);
 +                      item = string_list_append(&states->push, "(matching)");
                else if (strlen(spec->src))
 -                      item = string_list_append(spec->src, &states->push);
 +                      item = string_list_append(&states->push, spec->src);
                else
 -                      item = string_list_append("(delete)", &states->push);
 +                      item = string_list_append(&states->push, "(delete)");
  
                info = item->util = xcalloc(sizeof(struct push_info), 1);
                info->forced = spec->force;
@@@ -473,7 -428,7 +473,7 @@@ static int get_head_names(const struct 
        matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
                                    fetch_map, 1);
        for (ref = matches; ref; ref = ref->next)
 -              string_list_append(abbrev_branch(ref->name), &states->heads);
 +              string_list_append(&states->heads, abbrev_branch(ref->name));
  
        free_refs(fetch_map);
        free_refs(matches);
@@@ -533,12 -488,12 +533,12 @@@ static int add_branch_for_removal(cons
                        return 0;
        }
  
 -      /* don't delete non-remote refs */
 -      if (prefixcmp(refname, "refs/remotes")) {
 +      /* don't delete non-remote-tracking refs */
 +      if (prefixcmp(refname, "refs/remotes/")) {
                /* advise user how to delete local branches */
                if (!prefixcmp(refname, "refs/heads/"))
 -                      string_list_append(abbrev_branch(refname),
 -                                         branches->skipped);
 +                      string_list_append(branches->skipped,
 +                                         abbrev_branch(refname));
                /* silently skip over other non-remote refs */
                return 0;
        }
        if (flags & REF_ISSYMREF)
                return unlink(git_path("%s", refname));
  
 -      item = string_list_append(refname, branches->branches);
 +      item = string_list_append(branches->branches, refname);
        item->util = xmalloc(20);
        hashcpy(item->util, sha1);
  
@@@ -570,10 -525,10 +570,10 @@@ static int read_remote_branches(const c
        unsigned char orig_sha1[20];
        const char *symref;
  
 -      strbuf_addf(&buf, "refs/remotes/%s", rename->old);
 +      strbuf_addf(&buf, "refs/remotes/%s/", rename->old);
        if (!prefixcmp(refname, buf.buf)) {
 -              item = string_list_append(xstrdup(refname), rename->remote_branches);
 -              symref = resolve_ref(refname, orig_sha1, 1, &flag);
 +              item = string_list_append(rename->remote_branches, xstrdup(refname));
 +              symref = resolve_ref_unsafe(refname, orig_sha1, 1, &flag);
                if (flag & REF_ISSYMREF)
                        item->util = xstrdup(symref);
                else
@@@ -621,11 -576,10 +621,11 @@@ static int mv(int argc, const char **ar
                OPT_END()
        };
        struct remote *oldremote, *newremote;
 -      struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
 -      struct string_list remote_branches = { NULL, 0, 0, 0 };
 +      struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT,
 +              old_remote_context = STRBUF_INIT;
 +      struct string_list remote_branches = STRING_LIST_INIT_NODUP;
        struct rename_info rename;
 -      int i;
 +      int i, refspec_updated = 0;
  
        if (argc != 3)
                usage_with_options(builtin_remote_rename_usage, options);
        strbuf_addf(&buf, "remote.%s.fetch", rename.new);
        if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
                return error("Could not remove config section '%s'", buf.buf);
 +      strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old);
        for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
                char *ptr;
  
                strbuf_reset(&buf2);
                strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
 -              ptr = strstr(buf2.buf, rename.old);
 -              if (ptr)
 -                      strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
 -                                      rename.new, strlen(rename.new));
 +              ptr = strstr(buf2.buf, old_remote_context.buf);
 +              if (ptr) {
 +                      refspec_updated = 1;
 +                      strbuf_splice(&buf2,
 +                                    ptr-buf2.buf + strlen(":refs/remotes/"),
 +                                    strlen(rename.old), rename.new,
 +                                    strlen(rename.new));
 +              } else
 +                      warning("Not updating non-default fetch respec\n"
 +                              "\t%s\n"
 +                              "\tPlease update the configuration manually if necessary.",
 +                              buf2.buf);
 +
                if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
                        return error("Could not append '%s'", buf.buf);
        }
                }
        }
  
 +      if (!refspec_updated)
 +              return 0;
 +
        /*
         * First remove symrefs, then rename the rest, finally create
         * the new symrefs.
                int flag = 0;
                unsigned char sha1[20];
  
 -              resolve_ref(item->string, sha1, 1, &flag);
 +              read_ref_full(item->string, sha1, 1, &flag);
                if (!(flag & REF_ISSYMREF))
                        continue;
                if (delete_ref(item->string, NULL, REF_NODEREF))
@@@ -774,16 -715,13 +774,16 @@@ static int rm(int argc, const char **ar
        struct remote *remote;
        struct strbuf buf = STRBUF_INIT;
        struct known_remotes known_remotes = { NULL, NULL };
 -      struct string_list branches = { NULL, 0, 0, 1 };
 -      struct string_list skipped = { NULL, 0, 0, 1 };
 -      struct branches_for_remote cb_data = {
 -              NULL, &branches, &skipped, &known_remotes
 -      };
 +      struct string_list branches = STRING_LIST_INIT_DUP;
 +      struct string_list skipped = STRING_LIST_INIT_DUP;
 +      struct branches_for_remote cb_data;
        int i, result;
  
 +      memset(&cb_data, 0, sizeof(cb_data));
 +      cb_data.branches = &branches;
 +      cb_data.skipped = &skipped;
 +      cb_data.keep = &known_remotes;
 +
        if (argc != 2)
                usage_with_options(builtin_remote_rm_usage, options);
  
  
        if (skipped.nr) {
                fprintf(stderr, skipped.nr == 1 ?
 -                      "Note: A non-remote branch was not removed; "
 +                      "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
                        "to delete it, use:\n" :
 -                      "Note: Non-remote branches were not removed; "
 +                      "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
                        "to delete them, use:\n");
                for (i = 0; i < skipped.nr; i++)
                        fprintf(stderr, "  git branch -d %s\n",
@@@ -872,7 -810,7 +872,7 @@@ static int append_ref_to_tracked_list(c
        memset(&refspec, 0, sizeof(refspec));
        refspec.dst = (char *)refname;
        if (!remote_find_tracking(states->remote, &refspec))
 -              string_list_append(abbrev_branch(refspec.src), &states->tracked);
 +              string_list_append(&states->tracked, abbrev_branch(refspec.src));
  
        return 0;
  }
@@@ -925,7 -863,7 +925,7 @@@ static int add_remote_to_show_info(stru
        int n = strlen(item->string);
        if (n > info->width)
                info->width = n;
 -      string_list_insert(item->string, info->list);
 +      string_list_insert(info->list, item->string);
        return 0;
  }
  
@@@ -972,7 -910,7 +972,7 @@@ static int add_local_to_show_info(struc
        if (branch_info->rebase)
                show_info->any_rebase = 1;
  
 -      item = string_list_insert(branch_item->string, show_info->list);
 +      item = string_list_insert(show_info->list, branch_item->string);
        item->util = branch_info;
  
        return 0;
@@@ -1020,7 -958,7 +1020,7 @@@ static int add_push_to_show_info(struc
                show_info->width = n;
        if ((n = strlen(push_info->dest)) > show_info->width2)
                show_info->width2 = n;
 -      item = string_list_append(push_item->string, show_info->list);
 +      item = string_list_append(show_info->list, push_item->string);
        item->util = push_item->util;
        return 0;
  }
@@@ -1084,7 -1022,7 +1084,7 @@@ static int show(int argc, const char **
                OPT_END()
        };
        struct ref_states states;
 -      struct string_list info_list = { NULL, 0, 0, 0 };
 +      struct string_list info_list = STRING_LIST_INIT_NODUP;
        struct show_info info;
  
        argc = parse_options(argc, argv, NULL, options, builtin_remote_show_usage,
                        url = states.remote->url;
                        url_nr = states.remote->url_nr;
                }
 -              for (i=0; i < url_nr; i++)
 +              for (i = 0; i < url_nr; i++)
                        printf("  Push  URL: %s\n", url[i]);
                if (!i)
                        printf("  Push  URL: %s\n", "(no URL)");
  
                /* remote branch info */
                info.width = 0;
 -              for_each_string_list(add_remote_to_show_info, &states.new, &info);
 -              for_each_string_list(add_remote_to_show_info, &states.tracked, &info);
 -              for_each_string_list(add_remote_to_show_info, &states.stale, &info);
 +              for_each_string_list(&states.new, add_remote_to_show_info, &info);
 +              for_each_string_list(&states.tracked, add_remote_to_show_info, &info);
 +              for_each_string_list(&states.stale, add_remote_to_show_info, &info);
                if (info.list->nr)
                        printf("  Remote branch%s:%s\n",
                               info.list->nr > 1 ? "es" : "",
                                no_query ? " (status not queried)" : "");
 -              for_each_string_list(show_remote_info_item, info.list, &info);
 +              for_each_string_list(info.list, show_remote_info_item, &info);
                string_list_clear(info.list, 0);
  
                /* git pull info */
                info.width = 0;
                info.any_rebase = 0;
 -              for_each_string_list(add_local_to_show_info, &branch_list, &info);
 +              for_each_string_list(&branch_list, add_local_to_show_info, &info);
                if (info.list->nr)
                        printf("  Local branch%s configured for 'git pull':\n",
                               info.list->nr > 1 ? "es" : "");
 -              for_each_string_list(show_local_info_item, info.list, &info);
 +              for_each_string_list(info.list, show_local_info_item, &info);
                string_list_clear(info.list, 0);
  
                /* git push info */
                        printf("  Local refs will be mirrored by 'git push'\n");
  
                info.width = info.width2 = 0;
 -              for_each_string_list(add_push_to_show_info, &states.push, &info);
 +              for_each_string_list(&states.push, add_push_to_show_info, &info);
                qsort(info.list->items, info.list->nr,
                        sizeof(*info.list->items), cmp_string_with_push);
                if (info.list->nr)
                        printf("  Local ref%s configured for 'git push'%s:\n",
                                info.list->nr > 1 ? "s" : "",
                                no_query ? " (status not queried)" : "");
 -              for_each_string_list(show_push_info_item, info.list, &info);
 +              for_each_string_list(info.list, show_push_info_item, &info);
                string_list_clear(info.list, 0);
  
                free_remote_ref_states(&states);
@@@ -1219,9 -1157,10 +1219,9 @@@ static int set_head(int argc, const cha
                usage_with_options(builtin_remote_sethead_usage, options);
  
        if (head_name) {
 -              unsigned char sha1[20];
                strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
                /* make sure it's valid */
 -              if (!resolve_ref(buf2.buf, sha1, 1, NULL))
 +              if (!ref_exists(buf2.buf))
                        result |= error("Not a valid ref: %s", buf2.buf);
                else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
                        result |= error("Could not setup %s", buf.buf);
@@@ -1239,7 -1178,7 +1239,7 @@@ static int prune(int argc, const char *
  {
        int dry_run = 0, result = 0;
        struct option options[] = {
 -              OPT__DRY_RUN(&dry_run),
 +              OPT__DRY_RUN(&dry_run, "dry run"),
                OPT_END()
        };
  
@@@ -1425,7 -1364,7 +1425,7 @@@ static int set_url(int argc, const cha
                            "delete URLs"),
                OPT_END()
        };
 -      argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
 +      argc = parse_options(argc, argv, NULL, options, builtin_remote_seturl_usage,
                             PARSE_OPT_KEEP_ARGV0);
  
        if (add_mode && delete_mode)
@@@ -1499,10 -1438,10 +1499,10 @@@ static int get_one_entry(struct remote 
  
        if (remote->url_nr > 0) {
                strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
 -              string_list_append(remote->name, list)->util =
 +              string_list_append(list, remote->name)->util =
                                strbuf_detach(&url_buf, NULL);
        } else
 -              string_list_append(remote->name, list)->util = NULL;
 +              string_list_append(list, remote->name)->util = NULL;
        if (remote->pushurl_nr) {
                url = remote->pushurl;
                url_nr = remote->pushurl_nr;
        for (i = 0; i < url_nr; i++)
        {
                strbuf_addf(&url_buf, "%s (push)", url[i]);
 -              string_list_append(remote->name, list)->util =
 +              string_list_append(list, remote->name)->util =
                                strbuf_detach(&url_buf, NULL);
        }
  
  
  static int show_all(void)
  {
 -      struct string_list list = { NULL, 0, 0 };
 +      struct string_list list = STRING_LIST_INIT_NODUP;
        int result;
  
        list.strdup_strings = 1;
  int cmd_remote(int argc, const char **argv, const char *prefix)
  {
        struct option options[] = {
 -              OPT_BOOLEAN('v', "verbose", &verbose, "be verbose; must be placed before a subcommand"),
 +              OPT__VERBOSE(&verbose, "be verbose; must be placed before a subcommand"),
                OPT_END()
        };
        int result;