{"thread":{"id":"1600","subject":"Updated multi-head downloads and $GIT_DIR/remotes/ support","startedAt":"2005-08-20T18:13:10Z","lastAt":"2005-08-20T18:25:32Z","messageCount":7,"participants":["Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"7589","messageId":"7vvf20o4sp.fsf@assigned-by-dhcp.cox.net","threadId":"1600","inReplyTo":null,"subject":"Updated multi-head downloads and $GIT_DIR/remotes/ support","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-20T18:13:10Z","receivedAt":"2005-08-20T18:13:10Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Now I think all the pieces are glued together.  I'll send the\nfollowing patches, which are already in the proposed updates\nbranch.\n\nI sent an early WIP for some of them, but the patches are\nreorganized for easier review and applies on top of the current\n\"master\" branch.\n\nThis series consists of the following:\n\n    Start adding the $GIT_DIR/remotes/ support.\n    Multi-head fetch.\n    Retire git-parse-remote.\n    Infamous 'octopus merge'\n    Make \"git pull\" and \"git fetch\" default to origin\n    Use .git/remote/origin, not .git/branches/origin.\n\nThe issues I discussed in \"Multi-head fetches, pulls, and a King\nGhidorah\" are addressed there, and the examples in \"MyGITDay\"\nmessage I sent earlier should work with these patches.  I'll\nwork on adding some documentation, maybe in howto or tutorial\nformat, over the weekend.\n\n-jc\n"},{"id":"7590","messageId":"7vhddko4co.fsf@assigned-by-dhcp.cox.net","threadId":"1600","inReplyTo":"7vvf20o4sp.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Start adding the $GIT_DIR/remotes/ support.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-20T18:22:47Z","receivedAt":"2005-08-20T18:22:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"All the necessary parsing code is in git-parse-remote-script;\nupdate git-push-script to use it.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n    ** sorry I made a mistake of letting git send-email to\n    ** send nonsense messages ...\n\n Makefile                |    2 -\n git-parse-remote-script |  144 +++++++++++++++++++++++++++++++++++++++++++++++\n git-push-script         |   28 ++-------\n 3 files changed, 151 insertions(+), 23 deletions(-)\n create mode 100755 git-parse-remote-script\n\n284ba9655aedbdaaa897fdcc6aabae97de8d99d1\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -64,7 +64,7 @@ SCRIPTS=git git-apply-patch-script git-m\n \tgit-reset-script git-add-script git-checkout-script git-clone-script \\\n \tgitk git-cherry git-rebase-script git-relink-script git-repack-script \\\n \tgit-format-patch-script git-sh-setup-script git-push-script \\\n-\tgit-branch-script git-parse-remote git-verify-tag-script \\\n+\tgit-branch-script git-parse-remote git-parse-remote-script git-verify-tag-script \\\n \tgit-ls-remote-script git-clone-dumb-http git-rename-script \\\n \tgit-request-pull-script git-bisect-script\n \ndiff --git a/git-parse-remote-script b/git-parse-remote-script\nnew file mode 100755\n--- /dev/null\n+++ b/git-parse-remote-script\n@@ -0,0 +1,144 @@\n+#!/bin/sh\n+\n+. git-sh-setup-script || die \"Not a git archive\"\n+\n+get_data_source () {\n+\tcase \"$1\" in\n+\t*/*)\n+\t\t# Not so fast.  This could be the partial URL shorthand...\n+\t\ttoken=$(expr \"$1\" : '\\([^/]*\\)/')\n+\t\tremainder=$(expr \"$1\" : '[^/]*/\\(.*\\)')\n+\t\tif test -f \"$GIT_DIR/branches/$token\"\n+\t\tthen\n+\t\t\techo branches-partial\n+\t\telse\n+\t\t\techo ''\n+\t\tfi\n+\t\t;;\n+\t*)\n+\t\tif test -f \"$GIT_DIR/remotes/$1\"\n+\t\tthen\n+\t\t\techo remotes\n+\t\telif test -f \"$GIT_DIR/branches/$1\"\n+\t\tthen\n+\t\t\techo branches\n+\t\telse\n+\t\t\techo ''\n+\t\tfi ;;\n+\tesac\n+}\n+\n+get_remote_url () {\n+\tdata_source=$(get_data_source \"$1\")\n+\tcase \"$data_source\" in\n+\t'')\n+\t\techo \"$1\" ;;\n+\tremotes)\n+\t\tsed -ne '/^URL: */{\n+\t\t\ts///p\n+\t\t\tq\n+\t\t}' \"$GIT_DIR/remotes/$1\" ;;\n+\tbranches)\n+\t\tsed -e 's/#.*//' \"$GIT_DIR/branches/$1\" ;;\n+\tbranches-partial)\n+\t\ttoken=$(expr \"$1\" : '\\([^/]*\\)/')\n+\t\tremainder=$(expr \"$1\" : '[^/]*/\\(.*\\)')\n+\t\turl=$(sed -e 's/#.*//' \"$GIT_DIR/branches/$token\")\n+\t\techo \"$url/$remainder\"\n+\t\t;;\n+\t*)\n+\t\tdie \"internal error: get-remote-url $1\" ;;\n+\tesac\n+}\n+\n+get_remote_default_refs_for_push () {\n+\tdata_source=$(get_data_source \"$1\")\n+\tcase \"$data_source\" in\n+\t'' | branches | branches-partial)\n+\t\t;; # no default push mapping, just send matching refs.\n+\tremotes)\n+\t\tsed -ne '/^Push: */{\n+\t\t\ts///p\n+\t\t}' \"$GIT_DIR/remotes/$1\" ;;\n+\t*)\n+\t\tdie \"internal error: get-remote-default-ref-for-push $1\" ;;\n+\tesac\n+}\n+\n+# Subroutine to canonicalize remote:local notation\n+canon_refs_list_for_fetch () {\n+\tfor ref\n+\tdo\n+\t\texpr \"$ref\" : '.*:' >/dev/null || ref=\"${ref}:\"\n+\t\tremote=$(expr \"$ref\" : '\\([^:]*\\):')\n+\t\tlocal=$(expr \"$ref\" : '[^:]*:\\(.*\\)')\n+\t\tcase \"$remote\" in\n+\t\t'') remote=HEAD ;;\n+\t\t*) remote=\"refs/heads/$remote\" ;;\n+\t\tesac\n+\t\tcase \"$local\" in\n+\t\t'') local= ;;\n+\t\t*) local=\"refs/heads/$local\" ;;\n+\t\tesac\n+\t\techo \"${remote}:${local}\"\n+\tdone\n+}\n+\n+# Returns list of src: (no store), or src:dst (store)\n+get_remote_default_refs_for_fetch () {\n+\tdata_source=$(get_data_source \"$1\")\n+\tcase \"$data_source\" in\n+\t'' | branches-partial)\n+\t\techo \"HEAD:\" ;;\n+\tbranches)\n+\t\tremote_branch=$(sed -ne '/#/s/.*#//p' \"$GIT_DIR/branches/$1\")\n+\t\tcase \"$remote_branch\" in '') remote_branch=master ;; esac\n+\t\techo \"refs/heads/${remote_branch}:refs/heads/$1\"\n+\t\t;;\n+\tremotes)\n+\t\tcanon_refs_list_for_fetch $(sed -ne '/^Pull: */{\n+\t\t\t\t\t\ts///p\n+\t\t\t\t\t}' \"$GIT_DIR/remotes/$1\")\n+\t\t;;\n+\t*)\n+\t\tdie \"internal error: get-remote-default-ref-for-push $1\" ;;\n+\tesac\n+}\n+\n+get_remote_refs_for_push () {\n+\tcase \"$#\" in\n+\t0) die \"internal error: get-remote-refs-for-push.\" ;;\n+\t1) get_remote_default_refs_for_push \"$@\" ;;\n+\t*) shift; echo \"$@\" ;;\n+\tesac\n+}\n+\n+get_remote_refs_for_fetch () {\n+\tcase \"$#\" in\n+\t0)\n+\t    die \"internal error: get-remote-refs-for-fetch.\" ;;\n+\t1)\n+\t    get_remote_default_refs_for_fetch \"$@\" ;;\n+\t*)\n+\t    shift\n+\t    tag_just_seen=\n+\t    for ref\n+\t    do\n+\t\tif test \"$tag_just_seen\"\n+\t\tthen\n+\t\t    echo \"refs/tags/${ref}:refs/tags/${ref}\"\n+\t\t    tag_just_seen=\n+\t\t    continue\n+\t\telse\n+\t\t    case \"$ref\" in\n+\t\t    tag)\n+\t\t        tag_just_seen=yes\n+\t\t\tcontinue\n+\t\t\t;;\n+\t\t    esac\n+\t\tfi\n+\t        canon_refs_list_for_fetch \"$ref\"\n+\t    done\n+\t    ;;\n+\tesac\n+}\ndiff --git a/git-push-script b/git-push-script\n--- a/git-push-script\n+++ b/git-push-script\n@@ -20,8 +20,6 @@ do\n \t-*)\n \t\tdie \"Unknown parameter $1\" ;;\n         *)\n-\t\tremote=\"$1\"\n-\t\tshift\n \t\tset x \"$@\"\n \t\tshift\n \t\tbreak ;;\n@@ -29,27 +27,13 @@ do\n \tshift\n done\n \n-case \"$remote\" in\n-*:* | /* | ../* | ./* )\n-\t# An URL, host:/path/to/git, absolute and relative paths.\n-\t;;\n-* )\n-\t# Shorthand\n-\tif expr \"$remote\" : '..*/..*' >/dev/null\n-\tthen\n-\t\t# a short-hand followed by a trailing path\n-\t\tshorthand=$(expr \"$remote\" : '\\([^/]*\\)')\n-\t\tremainder=$(expr \"$remote\" : '[^/]*\\(/.*\\)$')\n-\telse\n-\t\tshorthand=\"$remote\"\n-\t\tremainder=\n-\tfi\n-\tremote=$(sed -e 's/#.*//' \"$GIT_DIR/branches/$remote\") &&\n-\texpr \"$remote\" : '..*:' >/dev/null &&\n-\tremote=\"$remote$remainder\" ||\n-\tdie \"Cannot parse remote $remote\"\n-\t;;\n+. git-parse-remote-script\n+remote=$(get_remote_url \"$@\")\n+case \"$has_all\" in\n+--all) set x ;;\n+'')    set x $(get_remote_refs_for_push \"$@\") ;;\n esac\n+shift\n \n case \"$remote\" in\n http://* | https://* | git://* | rsync://* )\n"},{"id":"7592","messageId":"7vmzncmpnv.fsf@assigned-by-dhcp.cox.net","threadId":"1600","inReplyTo":"7vvf20o4sp.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Multi-head fetch.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-20T18:25:24Z","receivedAt":"2005-08-20T18:25:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Traditionally, fetch takes these forms:\n\n    $ git fetch <remote>\n    $ git fetch <remote> <head>\n    $ git fetch <remote> tag <tag>\n\nThis patch updates it to take\n\n    $ git fetch <remote> <refspec>...\n\nwhere:\n\n    - A <refspec> of form \"<src>:<dst>\" is to fetch the objects\n      needed for the remote ref that matches <src>, and if <dst>\n      is not empty, store it as a local <dst>.\n\n    - \"tag\" followed by <next> is just an old way of saying\n      \"refs/tags/<next>:refs/tags/<next>\"; this mimics the\n      current behaviour of the third form above and means \"fetch\n      that tag and store it under the same name\".\n\n    - A single token <refspec> without colon is a shorthand for\n      \"<refspec>:\"  That is, \"fetch that ref but do not store\n      anywhere\".\n\n    - when there is no <refspec> specified\n\n      - if <remote> is the name of a file under $GIT_DIR/remotes/\n\t(i.e. a new-style shorthand), then it is the same as giving\n\tthe <refspec>s listed on Pull: line in that file.\n\n      - if <remote> is the name of a file under $GIT_DIR/branches/\n\t(i.e. an old-style shorthand, without trailing path), then it\n\tis the same as giving a single <refspec>\n\t\"<remote-name>:refs/heads/<remote>\" on the command line, where\n\t<remote-name> is the remote branch name (defaults to HEAD, but\n\tcan be overridden by .git/branches/<remote> file having the\n\tURL fragment notation).  That is, \"fetch that branch head and\n\tstore it in refs/heads/<remote>\".\n\n      - otherwise, it is the same as giving a single <refspec>\n        that is \"HEAD:\".\n\nThe SHA1 object names of fetched refs are stored in FETCH_HEAD,\none name per line, with a comment to describe where it came from.\nThis is later used by \"git resolve\" and \"git octopus\".\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n git-fetch-script |  193 ++++++++++++++++++++++++++++++++++++++++++------------\n 1 files changed, 149 insertions(+), 44 deletions(-)\n\nd947289005049c67f1dded517a1a6a8843fcf4a3\ndiff --git a/git-fetch-script b/git-fetch-script\n--- a/git-fetch-script\n+++ b/git-fetch-script\n@@ -1,54 +1,159 @@\n #!/bin/sh\n #\n . git-sh-setup-script || die \"Not a git archive\"\n-. git-parse-remote \"$@\"\n-merge_repo=\"$_remote_repo\"\n-merge_head=\"$_remote_head\"\n-merge_store=\"$_remote_store\"\n-\n-TMP_HEAD=\"$GIT_DIR/TMP_HEAD\"\n-\n-case \"$merge_repo\" in\n-http://* | https://*)\n-        if [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n-            curl_extra_args=\"-k\"\n-        fi\n-\t_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' &&\n-\t_x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\" &&\n-\thead=$(curl -nsf $curl_extra_args \"$merge_repo/$merge_head\") &&\n-\texpr \"$head\" : \"$_x40\\$\" >/dev/null || {\n-\t\techo >&2 \"Failed to fetch $merge_head from $merge_repo\"\n-\t        exit 1\n-\t}\n-\techo Fetching \"$merge_head\" using http\n-\tgit-http-pull -v -a \"$head\" \"$merge_repo/\" || exit\n-\t;;\n-rsync://*)\n-\trsync -L \"$merge_repo/$merge_head\" \"$TMP_HEAD\" || exit 1\n-\thead=$(git-rev-parse TMP_HEAD)\n-\trm -f \"$TMP_HEAD\"\n-\trsync -avz --ignore-existing \"$merge_repo/objects/\" \"$GIT_OBJECT_DIRECTORY/\"\n-\t;;\n+. git-parse-remote-script\n+_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'\n+_x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40\"\n+\n+append=\n+case \"$#\" in\n+0)\n+\tdie \"Where do you want to fetch from?\" ;;\n *)\n-\thead=$(git-fetch-pack \"$merge_repo\" \"$merge_head\")\n-\tif h=`expr \"$head\" : '\\([^ ][^ ]*\\) '`\n+\tcase \"$1\" in\n+\t-a|--a|--ap|--app|--appe|--appen|--append)\n+\t\tappend=t\n+\t\tshift ;;\n+\tesac\n+esac\n+remote_nick=\"$1\"\n+remote=$(get_remote_url \"$@\")\n+refs=\n+rref=\n+rsync_slurped_objects=\n+\n+if test \"\" = \"$append\"\n+then\n+\t: >$GIT_DIR/FETCH_HEAD\n+fi\n+\n+append_fetch_head () {\n+    head_=\"$1\"\n+    remote_=\"$2\"\n+    remote_name_=\"$3\"\n+    remote_nick_=\"$4\"\n+    local_name_=\"$5\"\n+\n+    # 2.6.11-tree tag would not be happy to be fed to resolve.\n+    if git-cat-file commit \"$head_\" >/dev/null 2>&1\n+    then\n+\thead_=$(git-rev-parse --verify \"$head_^0\") || exit\n+\tnote_=\"$head_\t$remote_name_ from $remote_nick_\"\n+\techo \"$note_\" >>$GIT_DIR/FETCH_HEAD\n+\techo >&2 \"* committish: $note_\"\n+    else\n+\techo >&2 \"* non-commit: $note_\"\n+    fi\n+    if test \"$local_name_\" != \"\"\n+    then\n+\t# We are storing the head locally.  Make sure that it is\n+\t# a fast forward (aka \"reverse push\").\n+\tfast_forward_local \"$local_name_\" \"$head_\" \"$remote_\" \"$remote_name_\"\n+    fi\n+}\n+\n+fast_forward_local () {\n+    case \"$1\" in\n+    refs/tags/*)\n+\t# Tags need not be pointing at commits so there\n+\t# is no way to guarantee \"fast-forward\" anyway.\n+\techo \"$2\" >\"$GIT_DIR/$1\" ;;\n+    refs/heads/*)\n+\t# NEEDSWORK: use the same cmpxchg protocol here.\n+\techo \"$2\" >\"$GIT_DIR/$1.lock\"\n+\tif test -f \"$GIT_DIR/$1\"\n \tthen\n-\t    head=$h\n+\t    local=$(git-rev-parse --verify \"$1^0\") &&\n+\t    mb=$(git-merge-base \"$local\" \"$2\") &&\n+\t    case \"$2,$mb\" in\n+\t    $local,*)\n+\t\techo >&2 \"* $1: same as $4\"\n+\t\techo >&2 \"  from $3\"\n+\t\t;;\n+\t    *,$local)\n+\t\techo >&2 \"* $1: fast forward to $4\"\n+\t\techo >&2 \"  from $3\"\n+\t\t;;\n+\t    *)\n+\t\tfalse\n+\t\t;;\n+\t    esac || {\n+\t\tmv \"$GIT_DIR/$1.lock\" \"$GIT_DIR/$1.remote\"\n+\t\techo >&2 \"* $1: does not fast forward to $4\"\n+\t\techo >&2 \"  from $3; leaving it in '$1.remote'\"\n+\t    }\n+\telse\n+\t\techo >&2 \"* $1: storing $4\"\n+\t\techo >&2 \"  from $3.\"\n \tfi\n+\ttest -f \"$GIT_DIR/$1.lock\" &&\n+\t    mv \"$GIT_DIR/$1.lock\" \"$GIT_DIR/$1\"\n \t;;\n-esac || exit 1\n-\n-git-rev-parse --verify \"$head\" > /dev/null || exit 1\n+    esac\n+}\n \n-case \"$merge_store\" in\n-'')\n+for ref in $(get_remote_refs_for_fetch \"$@\")\n+do\n+    refs=\"$refs $ref\"\n+\n+    # These are relative path from $GIT_DIR, typically starting at refs/\n+    # but may be HEAD\n+    remote_name=$(expr \"$ref\" : '\\([^:]*\\):')\n+    local_name=$(expr \"$ref\" : '[^:]*:\\(.*\\)')\n+\n+    rref=\"$rref $remote_name\"\n+\n+    # There are transports that can fetch only one head at a time...\n+    case \"$remote\" in\n+    http://* | https://*)\n+\tif [ -n \"$GIT_SSL_NO_VERIFY\" ]; then\n+\t    curl_extra_args=\"-k\"\n+\tfi\n+\thead=$(curl -nsf $curl_extra_args \"$remote/$remote_name\") &&\n+\texpr \"$head\" : \"$_x40\\$\" >/dev/null ||\n+\t    die \"Failed to fetch $remote_name from $remote\"\n+\techo Fetching \"$remote_name from $remote\" using http\n+\tgit-http-pull -v -a \"$head\" \"$remote/\" || exit\n \t;;\n+    rsync://*)\n+\tTMP_HEAD=\"$GIT_DIR/TMP_HEAD\"\n+\trsync -L \"$remote/$remote_name\" \"$TMP_HEAD\" || exit 1\n+\thead=$(git-rev-parse TMP_HEAD)\n+\trm -f \"$TMP_HEAD\"\n+\ttest \"$rsync_slurped_objects\" || {\n+\t    rsync -avz --ignore-existing \"$remote/objects/\" \\\n+\t\t\"$GIT_OBJECT_DIRECTORY/\" || exit\n+\t    rsync_slurped_objects=t\n+\t}\n+\t;;\n+    *)\n+\t# We will do git native transport with just one call later.\n+\tcontinue ;;\n+    esac\n+\n+    append_fetch_head \"$head\" \"$remote\" \"$remote_name\" \"$remote_nick\" \"$local_name\"\n+\n+done\n+\n+case \"$remote\" in\n+http://* | https://* | rsync://* )\n+    ;; # we are already done.\n *)\n-\techo \"$head\" > \"$GIT_DIR/$merge_store\"\n-esac &&\n-\n-# FETCH_HEAD is fed to git-resolve-script which will eventually be\n-# passed to git-commit-tree as one of the parents.  Make sure we do\n-# not give a tag object ID.\n-\n-git-rev-parse \"$head^0\" >\"$GIT_DIR/FETCH_HEAD\"\n+    git-fetch-pack \"$remote\" $rref |\n+    while read sha1 remote_name\n+    do\n+\tfound=\n+\tfor ref in $refs\n+\tdo\n+\t    case \"$ref\" in\n+\t    $remote_name:*)\n+\t\tfound=\"$ref\"\n+\t\tbreak ;;\n+\t    esac\n+\tdone\n+\n+\tlocal_name=$(expr \"$found\" : '[^:]*:\\(.*\\)')\n+        append_fetch_head \"$sha1\" \"$remote\" \"$remote_name\" \"$remote_nick\" \"$local_name\"\n+    done\n+    ;;\n+esac\n"},{"id":"7593","messageId":"7vhddkmpnt.fsf@assigned-by-dhcp.cox.net","threadId":"1600","inReplyTo":"7vvf20o4sp.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Retire git-parse-remote.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-20T18:25:26Z","receivedAt":"2005-08-20T18:25:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Update git-pull to match updated git-fetch and allow pull to\nfetch from multiple remote references.  There is no support for\nresolving more than two heads, which will be done with \"git\noctopus\".\n\nUpdate \"git ls-remote\" to use git-parse-remote-script.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n Makefile             |    2 +\n git-ls-remote-script |    4 +--\n git-parse-remote     |   79 --------------------------------------------------\n git-pull-script      |   14 ++++++---\n 4 files changed, 12 insertions(+), 87 deletions(-)\n delete mode 100755 git-parse-remote\n\n07c44b628e605c4e7fead8ff9e191711b7abe301\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -64,7 +64,7 @@ SCRIPTS=git git-apply-patch-script git-m\n \tgit-reset-script git-add-script git-checkout-script git-clone-script \\\n \tgitk git-cherry git-rebase-script git-relink-script git-repack-script \\\n \tgit-format-patch-script git-sh-setup-script git-push-script \\\n-\tgit-branch-script git-parse-remote git-parse-remote-script git-verify-tag-script \\\n+\tgit-branch-script git-parse-remote-script git-verify-tag-script \\\n \tgit-ls-remote-script git-clone-dumb-http git-rename-script \\\n \tgit-request-pull-script git-bisect-script\n \ndiff --git a/git-ls-remote-script b/git-ls-remote-script\n--- a/git-ls-remote-script\n+++ b/git-ls-remote-script\n@@ -29,8 +29,8 @@ case \",$heads,$tags,\" in\n ,,,) heads=heads tags=tags other=other ;;\n esac\n \n-. git-parse-remote \"$1\"\n-peek_repo=\"$_remote_repo\"\n+. git-parse-remote-script\n+peek_repo=\"$(get_remote_url)\"\n shift\n \n tmp=.ls-remote-$$\ndiff --git a/git-parse-remote b/git-parse-remote\ndeleted file mode 100755\n--- a/git-parse-remote\n+++ /dev/null\n@@ -1,79 +0,0 @@\n-: To be included in git-pull and git-fetch scripts.\n-\n-# A remote repository can be specified on the command line\n-# in one of the following formats:\n-#\n-#\t<repo>\n-#\t<repo> <head>\n-#\t<repo> tag <tag>\n-#\n-# where <repo> could be one of:\n-#\n-#\ta URL (including absolute or local pathname)\n-#\ta short-hand\n-#\ta short-hand followed by a trailing path\n-#\n-# A short-hand <name> has a corresponding file $GIT_DIR/branches/<name>,\n-# whose contents is a URL, possibly followed by a URL fragment #<head>\n-# to name the default branch on the remote side to fetch from.\n-\n-_remote_repo= _remote_store= _remote_head= _remote_name=\n-\n-case \"$1\" in\n-*:* | /* | ../* | ./* )\n-\t_remote_repo=\"$1\"\n-\t;;\n-* )\n-\t# otherwise, it is a short hand.\n-\tcase \"$1\" in\n-\t*/*)\n-\t\t# a short-hand followed by a trailing path\n-\t\t_token=$(expr \"$1\" : '\\([^/]*\\)/')\n-\t\t_rest=$(expr \"$1\" : '[^/]*\\(/.*\\)$')\n-\t\t;;\n-\t*)\n-\t\t_token=\"$1\"\n-\t\t_rest=\n-\t\t_remote_store=\"refs/heads/$_token\"\n-\t\t;;\n-\tesac\n-\ttest -f \"$GIT_DIR/branches/$_token\" ||\n-\tdie \"No such remote branch: $_token\"\n-\n-\t_remote_repo=$(cat \"$GIT_DIR/branches/$_token\")\"$_rest\"\n-\t;;\n-esac\n-\n-case \"$_remote_repo\" in\n-*\"#\"*)\n-\t_remote_head=`expr \"$_remote_repo\" : '.*#\\(.*\\)$'`\n-\t_remote_repo=`expr \"$_remote_repo\" : '\\(.*\\)#'`\n-\t;;\n-esac\n-\n-_remote_name=$(echo \"$_remote_repo\" | sed 's|\\.git/*$||')\n-\n-case \"$2\" in\n-tag)\n-\t_remote_name=\"tag '$3' of $_remote_name\"\n-\t_remote_head=\"refs/tags/$3\"\n-\t_remote_store=\"$_remote_head\"\n-\t;;\n-?*)\n-\t# command line specified a head explicitly; do not\n-\t# store the fetched head as a branch head.\n-\t_remote_name=\"head '$2' of $_remote_name\"\n-\t_remote_head=\"refs/heads/$2\"\n-\t_remote_store=''\n-\t;;\n-'')\n-\tcase \"$_remote_head\" in\n-\t'')\n-\t\t_remote_head=HEAD ;;\n-\t*)\n-\t\t_remote_name=\"head '$_remote_head' of $_remote_name\"\n-\t\t_remote_head=\"refs/heads/$_remote_head\"\n-\t\t;;\n-\tesac\n-\t;;\n-esac\ndiff --git a/git-pull-script b/git-pull-script\n--- a/git-pull-script\n+++ b/git-pull-script\n@@ -1,12 +1,16 @@\n #!/bin/sh\n #\n . git-sh-setup-script || die \"Not a git archive\"\n-. git-parse-remote \"$@\"\n-merge_name=\"$_remote_name\"\n-\n git-fetch-script \"$@\" || exit 1\n+merge_head=$(sed -e 's/\t.*//' \"$GIT_DIR\"/FETCH_HEAD | tr '\\012' ' ')\n+merge_name=$(sed -e 's/^[0-9a-f]*\t//' \"$GIT_DIR\"/FETCH_HEAD |\n+\t tr '\\012' ' ')\n+\n+case \"$merge_head\" in\n+'' | *' '?*) die \"Cannot resolve multiple heads at the same time (yet).\" ;;\n+esac\n+\n \n git-resolve-script \\\n \t\"$(cat \"$GIT_DIR\"/HEAD)\" \\\n-\t\"$(cat \"$GIT_DIR\"/FETCH_HEAD)\" \\\n-\t\"Merge $merge_name\"\n+\t$merge_head \"Merge $merge_name\"\n"},{"id":"7595","messageId":"7vbr3smpnr.fsf@assigned-by-dhcp.cox.net","threadId":"1600","inReplyTo":"7vvf20o4sp.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Infamous 'octopus merge'","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-20T18:25:28Z","receivedAt":"2005-08-20T18:25:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This script uses the list of heads and their origin multi-head \"git\nfetch\" left in the $GIT_DIR/FETCH_HEAD file, and makes an octopus\nmerge on top of the current HEAD using them.\n\nThe implementation tries to be strict for the sake of safety.  It\ninsists that your working tree is clean (no local changes) and matches\nthe HEAD, and when any of the merged heads does not automerge, the\nwhole process is aborted and tries to rewind your working tree is to\nthe original state.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n Makefile           |    1 +\n git-octopus-script |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 104 insertions(+), 0 deletions(-)\n create mode 100755 git-octopus-script\n\n325918bdc88517826fb7f14fba87a34b92ea2b52\ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -72,6 +72,7 @@ SCRIPTS += git-count-objects-script\n # SCRIPTS += git-send-email-script\n SCRIPTS += git-revert-script\n SCRIPTS += git-show-branches-script\n+SCRIPTS += git-octopus-script\n \n PROG=   git-update-cache git-diff-files git-init-db git-write-tree \\\n \tgit-read-tree git-commit-tree git-cat-file git-fsck-cache \\\ndiff --git a/git-octopus-script b/git-octopus-script\nnew file mode 100755\n--- /dev/null\n+++ b/git-octopus-script\n@@ -0,0 +1,103 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Junio C Hamano\n+#\n+# Resolve two or more trees recorded in $GIT_DIR/FETCH_HEAD.\n+#\n+. git-sh-setup-script || die \"Not a git archive\"\n+\n+usage () {\n+    die \"usage: git octopus\"\n+}\n+\n+# Sanity check the heads early.\n+while read SHA1 REPO\n+do\n+\ttest $(git-cat-file -t $SHA1) = \"commit\" ||\n+\t\tdie \"$REPO given to octopus is not a commit\"\n+done <\"$GIT_DIR/FETCH_HEAD\"\n+\n+head=$(git-rev-parse --verify HEAD) || exit\n+\n+git-update-cache --refresh ||\n+\tdie \"Your working tree is dirty.\"\n+test \"$(git-diff-cache --cached \"$head\")\" = \"\" ||\n+\tdie \"Your working tree does not match HEAD.\"\n+\n+# MRC is the current \"merge reference commit\"\n+# MRT is the current \"merge result tree\"\n+\n+MRC=$head MSG= PARENT=\"-p $head\"\n+MRT=$(git-write-tree)\n+CNT=1 ;# counting our head\n+NON_FF_MERGE=0\n+while read SHA1 REPO\n+do\n+\tcommon=$(git-merge-base $MRC $SHA1) ||\n+\t\tdie \"Unable to find common commit with $SHA1 from $REPO\"\n+\n+\tif test \"$common\" = $SHA1\n+\tthen\n+\t\techo \"Already up-to-date: $REPO\"\n+\t\tcontinue\n+\tfi\n+\n+\tCNT=`expr $CNT + 1`\n+\tPARENT=\"$PARENT -p $SHA1\"\n+\tMSG=\"$MSG\n+\t$REPO\"\n+\n+\tif test \"$common,$NON_FF_MERGE\" = \"$MRC,0\"\n+\tthen\n+\t\t# The first head being merged was a fast-forward.\n+\t\t# Advance MRC to the head being merged, and use that\n+\t\t# tree as the intermediate result of the merge.\n+\t\t# We still need to count this as part of the parent set.\n+\n+\t\techo \"Fast forwarding to: $REPO\"\n+\t\tgit-read-tree -u -m $head $SHA1 || exit\n+\t\tMRC=$SHA1 MRT=$(git-write-tree)\n+\t\tcontinue\n+\tfi\n+\n+\tNON_FF_MERGE=1\n+\n+\techo \"Trying simple merge with $REPO\"\n+\tgit-read-tree -u -m $common $MRT $SHA1 || exit\n+\tnext=$(git-write-tree 2>/dev/null)\n+\tif test $? -ne 0\n+\tthen\n+\t\techo \"Simple merge did not work, trying automatic merge.\"\n+\t\tgit-merge-cache -o git-merge-one-file-script -a || {\n+\t\tgit-read-tree --reset \"$head\"\n+\t\tgit-checkout-tree -f -q -u -a\n+\t\tdie \"Automatic merge failed; should not be doing Octopus\"\n+\t\t}\n+\t\tnext=$(git-write-tree 2>/dev/null)\n+\tfi\n+\tMRC=$common\n+\tMRT=$next\n+done <\"$GIT_DIR/FETCH_HEAD\"\n+\n+# Just to be careful in case the user feeds nonsense to us.\n+case \"$CNT\" in\n+1)\n+\techo \"No changes.\"\n+\texit 0 ;;\n+2)\n+\techo \"Not an Octopus; making an ordinary commit.\"\n+\tMSG=\"Merge \"`expr \"$MSG\" : '.\t\\(.*\\)'` ; # remove LF and TAB\n+\t;;\n+*)\n+\t# In an octopus, the original head is just one of the equals,\n+\t# so we should list it as such.\n+\tHEAD_LINK=`readlink \"$GIT_DIR/HEAD\"`\n+\tMSG=\"Octopus merge of the following:\n+\n+\t$HEAD_LINK from .$MSG\"\n+\t;;\n+esac\n+result_commit=$(echo \"$MSG\" | git-commit-tree $MRT $PARENT)\n+echo \"Committed merge $result_commit\"\n+echo $result_commit >\"$GIT_DIR\"/HEAD\n+git-diff-tree -p $head $result_commit | git-apply --stat\n"},{"id":"7594","messageId":"7v64u0mpnp.fsf@assigned-by-dhcp.cox.net","threadId":"1600","inReplyTo":"7vvf20o4sp.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Make \"git pull\" and \"git fetch\" default to origin","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-20T18:25:30Z","receivedAt":"2005-08-20T18:25:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Amos Waterland sent in a patch for the pre-multi-head aware\nversion of \"git pull\" to do this, but the code changed quite a\nbit since then.  If there is no argument given to pull from, and\nif \"origin\" makes sense, default to fetch/pull from \"origin\"\ninstead of barfing.\n\n[jc: besides, the patch by Amos broke the non-default case where\nexplicit refspecs are specified, and did not make sure we know\nwhat \"origin\" means before defaulting to it.]\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n git-fetch-script |    5 ++++-\n 1 files changed, 4 insertions(+), 1 deletions(-)\n\n6d8fcdbf772f4fc4ec7ae67630b52bc8a07d7b6d\ndiff --git a/git-fetch-script b/git-fetch-script\n--- a/git-fetch-script\n+++ b/git-fetch-script\n@@ -8,7 +8,10 @@ _x40=\"$_x40$_x40$_x40$_x40$_x40$_x40$_x4\n append=\n case \"$#\" in\n 0)\n-\tdie \"Where do you want to fetch from?\" ;;\n+\ttest -f \"$GIT_DIR/branches/origin\" ||\n+\t\ttest -f \"$GIT_DIR/remotes/origin\" ||\n+\t\t\tdie \"Where do you want to fetch from?\"\n+\tset origin ;;\n *)\n \tcase \"$1\" in\n \t-a|--a|--ap|--app|--appe|--appen|--append)\n"},{"id":"7591","messageId":"7vzmrclb37.fsf@assigned-by-dhcp.cox.net","threadId":"1600","inReplyTo":"7vvf20o4sp.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Use .git/remote/origin, not .git/branches/origin.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-20T18:25:32Z","receivedAt":"2005-08-20T18:25:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Now multi-head fetch is complete, let's migrate the\ndefault configuration for new repositories created with\nthe \"git clone\" command.\n\nThe original $GIT_DIR/branches is not deprecated yet, but create\nremotes directory by default from the templates as well.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n git-clone-script    |    8 +++++---\n templates/remotes-- |    1 +\n 2 files changed, 6 insertions(+), 3 deletions(-)\n create mode 100644 templates/remotes--\n\n8ad3e7efb406377f6903171638c70b7d566254c5\ndiff --git a/git-clone-script b/git-clone-script\n--- a/git-clone-script\n+++ b/git-clone-script\n@@ -127,6 +127,8 @@ yes,yes)\n esac\n \n # Update origin.\n-mkdir -p \"$D/.git/branches/\" &&\n-rm -f \"$D/.git/branches/origin\" &&\n-echo \"$repo\" >\"$D/.git/branches/origin\"\n+mkdir -p \"$D/.git/remotes/\" &&\n+rm -f \"$D/.git/remotes/origin\" &&\n+echo >\"$D/.git/remotes/origin\" \\\n+\"URL: $repo\n+Pull: master:origin\"\ndiff --git a/templates/remotes-- b/templates/remotes--\nnew file mode 100644\n--- /dev/null\n+++ b/templates/remotes--\n@@ -0,0 +1 @@\n+: this is just to ensure the directory exists.\n"}]}