{"thread":{"id":"7206","subject":"[PATCH, 2nd version] git-fetch, git-branch: Support local --track via a special remote `.'","startedAt":"2007-03-12T17:14:44Z","lastAt":"2007-03-14T12:52:33Z","messageCount":6,"participants":["Paolo Bonzini","Junio C Hamano","Santi Béjar"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"36920","messageId":"45F58A84.2000503@lu.unisi.ch","threadId":"7206","inReplyTo":null,"subject":"[PATCH, 2nd version] git-fetch, git-branch: Support local --track via a special remote `.'","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@lu.unisi.ch","sentAt":"2007-03-12T17:14:44Z","receivedAt":"2007-03-12T17:14:44Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"This patch adds support for a dummy remote `.' to avoid having to declare\na fake remote like\n\n\t[remote \"local\"]\n\t\turl = .\n\t\tfetch = refs/heads/*:refs/heads/*\n\nSuch a builtin remote simplifies the operation of \"git-fetch\", which\nwill populate FETCH_HEAD but will not pretend that two repositories are\nin use, will not create a thin pack, and will not perform any useless\nremapping of names.  The speed improvement is around 20%, and it should\nimprove more if \"git-fetch\" is converted to a builtin.\n\nTo this end, git-parse-remote is grown with a new kind of remote, `builtin'.\nIn git-fetch.sh, we treat the builtin remote specially in that it needs no\npack/store operations.  In fact, doing git-fetch on a builtin remote will\nsimply populate FETCH_HEAD appropriately.\n\nThe patch also improves of the --track/--no-track support, extending\nit so that branch.<name>.remote items referring `.' can be created.\n\nSigned-off-by: Paolo Bonzini  <bonzini@gnu.org>\n---\n Documentation/config.txt |    4 ++++\n builtin-branch.c         |   39 +++++++++++++++++++++++++--------------\n git-fetch.sh             |    9 +++++++--\n git-parse-remote.sh      |   22 +++++++++++++++++++++-\n t/t3200-branch.sh        |    6 ++++++\n t/t5520-pull.sh          |   13 +++++++++++++\n 6 files changed, 76 insertions(+), 17 deletions(-)\n\n\tI hope this is what you meant in your reply to my message.\n\n\tI removed completely the configuration variable since it made\n\tno sense to me, either.\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5408dd6..28899d9 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -272,6 +272,10 @@ branch.<name>.merge::\n \t`git fetch`) to lookup the default branch for merging. Without\n \tthis option, `git pull` defaults to merge the first refspec fetched.\n \tSpecify multiple values to get an octopus merge.\n+\tIf you wish to setup `git pull` so that it merges into <name> from\n+\tanother branch in the local repository, you can point\n+\tbranch.<name>.merge to the desired branch, and use the special setting\n+\t`.` (a period) for branch.<name>.remote.\n \n color.branch::\n \tA boolean to enable/disable color in the output of\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 42b1ff1..14c4219 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -372,9 +372,26 @@ static int get_remote_config(const char *key, const char *value)\n \treturn 0;\n }\n \n-static void set_branch_defaults(const char *name, const char *real_ref)\n+static void set_branch_merge(const char *name, const char *config_remote,\n+\t\t\t     const char *config_repo)\n {\n \tchar key[1024];\n+\tif (sizeof(key) <=\n+\t    snprintf(key, sizeof(key), \"branch.%s.remote\", name))\n+\t\tdie(\"what a long branch name you have!\");\n+\tgit_config_set(key, config_remote);\n+\n+\t/*\n+\t * We do not have to check if we have enough space for\n+\t * the 'merge' key, since it's shorter than the\n+\t * previous 'remote' key, which we already checked.\n+\t */\n+\tsnprintf(key, sizeof(key), \"branch.%s.merge\", name);\n+\tgit_config_set(key, config_repo);\n+}\n+\n+static void set_branch_defaults(const char *name, const char *real_ref)\n+{\n \tconst char *slash = strrchr(real_ref, '/');\n \n \tif (!slash)\n@@ -384,21 +401,15 @@ static void set_branch_defaults(const char *name, const char *real_ref)\n \tstart_len = strlen(real_ref);\n \tbase_len = slash - real_ref;\n \tgit_config(get_remote_config);\n+\tif (!config_repo && !config_remote &&\n+\t    !prefixcmp(real_ref, \"refs/heads/\")) {\n+\t\tset_branch_merge(name, \".\", real_ref);\n+\t\tprintf(\"Branch %s set up to track local branch %s.\\n\",\n+\t\t       name, real_ref);\n+\t}\n \n \tif (config_repo && config_remote) {\n-\t\tif (sizeof(key) <=\n-\t\t    snprintf(key, sizeof(key), \"branch.%s.remote\", name))\n-\t\t\tdie(\"what a long branch name you have!\");\n-\t\tgit_config_set(key, config_remote);\n-\n-\t\t/*\n-\t\t * We do not have to check if we have enough space for\n-\t\t * the 'merge' key, since it's shorter than the\n-\t\t * previous 'remote' key, which we already checked.\n-\t\t */\n-\t\tsnprintf(key, sizeof(key), \"branch.%s.merge\", name);\n-\t\tgit_config_set(key, config_repo);\n-\n+\t\tset_branch_merge(name, config_remote, config_repo);\n \t\tprintf(\"Branch %s set up to track remote branch %s.\\n\",\n \t\t       name, real_ref);\n \t}\ndiff --git a/git-fetch.sh b/git-fetch.sh\nindex b9d7a75..e2a6878 100755\n--- a/git-fetch.sh\n+++ b/git-fetch.sh\n@@ -164,6 +164,12 @@ then\n fi\n \n fetch_native () {\n+  if test \"$(get_data_source $remote_nick)\" = builtin; then\n+    for name in $(get_remote_fetch_branches \"$remote_nick\"); do\n+      append_fetch_head $(git-rev-parse \"$name\") . \"$name\" \"$name\" || exit\n+    done\n+    return\n+  fi\n \n   eval=$(echo \"$1\" | git-fetch--tool parse-reflist \"-\")\n   eval \"$eval\"\n@@ -353,8 +359,7 @@ case \",$#,$remote_nick,\" in\n \tcurr_branch=$(git-symbolic-ref -q HEAD | sed -e 's|^refs/heads/||')\n \tmerge_branches=$(git-config \\\n \t\t--get-all \"branch.${curr_branch}.merge\" | sort -u)\n-\tfetch_branches=$(get_remote_default_refs_for_fetch -n $remote_nick |\n-\t\tsed -e 's/:.*$//g' -e 's/^+//' | sort -u)\n+\tfetch_branches=$(get_remote_fetch_branches $remote_nick)\n \ttest -n \"$merge_branches\" && test -n \"$fetch_branches\" &&\n \tmerge_branches=$(printf '%s\\n%s' \"$merge_branches\" \"$fetch_branches\" |\n \t\tsort | uniq -d)\ndiff --git a/git-parse-remote.sh b/git-parse-remote.sh\nindex 99e7184..bc7533a 100755\n--- a/git-parse-remote.sh\n+++ b/git-parse-remote.sh\n@@ -9,6 +9,9 @@ get_data_source () {\n \t*/*)\n \t\techo ''\n \t\t;;\n+\t.)\n+\t\techo builtin\n+\t\t;;\n \t*)\n \t\tif test \"$(git-config --get \"remote.$1.url\")\"\n \t\tthen\n@@ -31,6 +34,9 @@ get_remote_url () {\n \t'')\n \t\techo \"$1\"\n \t\t;;\n+\tbuiltin)\n+\t\techo \"$1\"\n+\t\t;;\n \tconfig)\n \t\tgit-config --get \"remote.$1.url\"\n \t\t;;\n@@ -57,7 +63,7 @@ get_default_remote () {\n get_remote_default_refs_for_push () {\n \tdata_source=$(get_data_source \"$1\")\n \tcase \"$data_source\" in\n-\t'' | branches)\n+\t'' | branches | builtin)\n \t\t;; # no default push mapping, just send matching refs.\n \tconfig)\n \t\tgit-config --get-all \"remote.$1.push\" ;;\n@@ -128,6 +134,8 @@ get_remote_default_refs_for_fetch () {\n \tcase \"$data_source\" in\n \t'')\n \t\tset explicit \"HEAD:\" ;;\n+\tbuiltin)\n+\t\tset glob ;;\n \tconfig)\n \t\tset $(expand_refs_wildcard \"$1\" \\\n \t\t\t$(git-config --get-all \"remote.$1.fetch\")) ;;\n@@ -154,6 +162,18 @@ get_remote_default_refs_for_fetch () {\n \tfi\n }\n \n+# Returns list of sources\n+get_remote_fetch_branches () {\n+\tdata_source=$(get_data_source \"$1\")\n+\tcase \"$data_source\" in\n+\tbuiltin)\n+\t        git-show-ref --heads | sed -n 's,.*[      ]refs/,refs/,p' ;;\n+\t*)\n+\t\tget_remote_default_refs_for_fetch -n \"$1\" | \\\n+\t\t\tsed -e 's/:.*$//g' -e 's/^+//' | sort -u ;;\n+\tesac\n+}\n+\n get_remote_refs_for_push () {\n \tcase \"$#\" in\n \t0) die \"internal error: get-remote-refs-for-push.\" ;;\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex 75c000a..9558bdb 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -145,9 +145,15 @@ test_expect_success 'test overriding tracking setup via --no-track' \\\n      git-config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n      (git-show-ref -q refs/remotes/local/master || git-fetch local) &&\n      git-branch --no-track my2 local/master &&\n+     git-config branch.autosetupmerge false &&\n      ! test $(git-config branch.my2.remote) = local &&\n      ! test $(git-config branch.my2.merge) = refs/heads/master'\n \n+test_expect_success 'test local tracking setup' \\\n+    'git branch --track my6 s &&\n+     test $(git-config branch.my6.remote) = . &&\n+     test $(git-config branch.my6.merge) = refs/heads/s'\n+\n # Keep this test last, as it changes the current branch\n cat >expect <<EOF\n 0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000\tbranch: Created from master\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 7eb3783..c424e5b 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -29,5 +29,18 @@ test_expect_success 'checking the results' '\n \tdiff file cloned/file\n '\n \n+test_expect_success 'test . as a remote' '\n+\n+\tgit branch copy master &&\n+\tgit config branch.copy.remote . &&\n+\tgit config branch.copy.merge refs/heads/master &&\n+\techo updated >file &&\n+\tgit commit -a -m updated &&\n+\tgit checkout copy &&\n+\ttest `cat file` = file &&\n+\tgit pull &&\n+\ttest `cat file` = updated\n+'\n+\n test_done\n \n"},{"id":"36990","messageId":"7v4poplceh.fsf@assigned-by-dhcp.cox.net","threadId":"7206","inReplyTo":"45F58A84.2000503@lu.unisi.ch","subject":"Re: [PATCH, 2nd version] git-fetch, git-branch: Support local --track via a special remote `.'","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-13T09:29:26Z","receivedAt":"2007-03-13T09:29:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Paolo Bonzini <paolo.bonzini@lu.unisi.ch> writes:\n\n> \tI hope this is what you meant in your reply to my message.\n\nAlmost, except I wouldn't have made this part of fetch_native()\nlike this:\n\n> diff --git a/git-fetch.sh b/git-fetch.sh\n> index b9d7a75..e2a6878 100755\n> --- a/git-fetch.sh\n> +++ b/git-fetch.sh\n> @@ -164,6 +164,12 @@ then\n>  fi\n>  \n>  fetch_native () {\n> +  if test \"$(get_data_source $remote_nick)\" = builtin; then\n> +    for name in $(get_remote_fetch_branches \"$remote_nick\"); do\n> +      append_fetch_head $(git-rev-parse \"$name\") . \"$name\" \"$name\" || exit\n> +    done\n> +    return\n> +  fi\n>  \n>    eval=$(echo \"$1\" | git-fetch--tool parse-reflist \"-\")\n>    eval \"$eval\"\n\nbut probably would have created another sub, fetch_fake.\n\n> \tI removed completely the configuration variable since it made\n> \tno sense to me, either.\n\nI think that is sensible.\n\nCurrently the patch is parked at the tip of 'pu' after merging\nall the other topics, as the test t9101 seems to expose breakage\nin \"git pull . remotes/git-svn\".\n"},{"id":"36994","messageId":"45F69939.6070909@lu.unisi.ch","threadId":"7206","inReplyTo":"7v4poplceh.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH, fixed version] git-fetch, git-branch: Support local --track via a special remote `.'","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@lu.unisi.ch","sentAt":"2007-03-13T12:29:45Z","receivedAt":"2007-03-13T12:29:45Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"This patch on top of next adds support for a dummy remote `.' to\navoid having to declare a fake remote like\n\n\t[remote \"local\"]\n\t\turl = .\n\t\tfetch = refs/heads/*:refs/heads/*\n\nSuch a builtin remote simplifies the operation of \"git-fetch\", which\nwill populate FETCH_HEAD but will not pretend that two repositories are\nin use, will not create a thin pack, and will not perform any useless\nremapping of names.  The speed improvement is around 20%, and it should\nimprove more if \"git-fetch\" is converted to a builtin.\n\nTo this end, git-parse-remote is grown with a new kind of remote, `builtin'.\nIn git-fetch.sh, we treat the builtin remote specially in that it needs no\npack/store operations.  In fact, doing git-fetch on a builtin remote will\nsimply populate FETCH_HEAD appropriately.\n\nThe patch also improves of the --track/--no-track support, extending\nit so that branch.<name>.remote items referring `.' can be created.\nFinally, it fixes a typo in git-checkout.sh.\n\nThe patch was tested including the git-svn tests and has no regression.\n\nSigned-off-by: Paolo Bonzini  <bonzini@gnu.org>\n---\n Documentation/config.txt |    4 ++++\n builtin-branch.c         |   39 +++++++++++++++++++++++++--------------\n git-checkout.sh          |    2 +-\n git-fetch.sh             |   30 +++++++++++++++++++-----------\n git-parse-remote.sh      |   22 +++++++++++++++++++++-\n t/t3200-branch.sh        |    6 ++++++\n t/t5520-pull.sh          |   13 +++++++++++++\n t/t9109-git-svn-pull.sh  |   31 +++++++++++++++++++++++++++++++\n 8 files changed, 120 insertions(+), 27 deletions(-)\n\n\tThe failure, which I didn't see because I didn't have svn-perl\n\tbindings installed, was caused by my usage of \"git-show-ref --heads\"\n\twhere I should have used plain \"git-show-ref\".\n\n\tI include a smaller testcase for the same problem, t9109.\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5408dd6..28899d9 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -272,6 +272,10 @@ branch.<name>.merge::\n \t`git fetch`) to lookup the default branch for merging. Without\n \tthis option, `git pull` defaults to merge the first refspec fetched.\n \tSpecify multiple values to get an octopus merge.\n+\tIf you wish to setup `git pull` so that it merges into <name> from\n+\tanother branch in the local repository, you can point\n+\tbranch.<name>.merge to the desired branch, and use the special setting\n+\t`.` (a period) for branch.<name>.remote.\n \n color.branch::\n \tA boolean to enable/disable color in the output of\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 42b1ff1..14c4219 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -372,9 +372,26 @@ static int get_remote_config(const char *key, const char *value)\n \treturn 0;\n }\n \n-static void set_branch_defaults(const char *name, const char *real_ref)\n+static void set_branch_merge (const char *name, const char *config_remote,\n+\t\t\t      const char *config_repo)\n {\n \tchar key[1024];\n+\tif (sizeof(key) <=\n+\t    snprintf(key, sizeof(key), \"branch.%s.remote\", name))\n+\t\tdie(\"what a long branch name you have!\");\n+\tgit_config_set(key, config_remote);\n+\n+\t/*\n+\t * We do not have to check if we have enough space for\n+\t * the 'merge' key, since it's shorter than the\n+\t * previous 'remote' key, which we already checked.\n+\t */\n+\tsnprintf(key, sizeof(key), \"branch.%s.merge\", name);\n+\tgit_config_set(key, config_repo);\n+}\n+\n+static void set_branch_defaults(const char *name, const char *real_ref)\n+{\n \tconst char *slash = strrchr(real_ref, '/');\n \n \tif (!slash)\n@@ -384,21 +401,15 @@ static void set_branch_defaults(const char *name, const char *real_ref)\n \tstart_len = strlen(real_ref);\n \tbase_len = slash - real_ref;\n \tgit_config(get_remote_config);\n+\tif (!config_repo && !config_remote &&\n+\t    !prefixcmp (real_ref, \"refs/heads/\")) {\n+\t\tset_branch_merge (name, \".\", real_ref);\n+\t\tprintf(\"Branch %s set up to track local branch %s.\\n\",\n+\t\t       name, real_ref);\n+\t}\n \n \tif (config_repo && config_remote) {\n-\t\tif (sizeof(key) <=\n-\t\t    snprintf(key, sizeof(key), \"branch.%s.remote\", name))\n-\t\t\tdie(\"what a long branch name you have!\");\n-\t\tgit_config_set(key, config_remote);\n-\n-\t\t/*\n-\t\t * We do not have to check if we have enough space for\n-\t\t * the 'merge' key, since it's shorter than the\n-\t\t * previous 'remote' key, which we already checked.\n-\t\t */\n-\t\tsnprintf(key, sizeof(key), \"branch.%s.merge\", name);\n-\t\tgit_config_set(key, config_repo);\n-\n+\t\tset_branch_merge (name, config_remote, config_repo);\n \t\tprintf(\"Branch %s set up to track remote branch %s.\\n\",\n \t\t       name, real_ref);\n \t}\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 6caa9fd..b292ff0 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -89,7 +89,7 @@ while [ \"$#\" != \"0\" ]; do\n     esac\n done\n \n-case \"$new_branch,$track\" in\n+case \"$newbranch,$track\" in\n ,--*)\n \tdie \"git checkout: --track and --no-track require -b\"\n esac\ndiff --git a/git-fetch.sh b/git-fetch.sh\nindex b9d7a75..f06fa59 100755\n--- a/git-fetch.sh\n+++ b/git-fetch.sh\n@@ -163,8 +163,13 @@ then\n \tfi\n fi\n \n-fetch_native () {\n+fetch_builtin () {\n+    for name in $(get_remote_fetch_branches \"$remote_nick\"); do\n+      append_fetch_head $(git-rev-parse \"$name\") . \"$name\" \"$name\" || exit\n+    done\n+}\n \n+fetch_native () {\n   eval=$(echo \"$1\" | git-fetch--tool parse-reflist \"-\")\n   eval \"$eval\"\n \n@@ -291,14 +296,18 @@ fetch_dumb () {\n }\n \n fetch_main () {\n-\tcase \"$remote\" in\n-\thttp://* | https://* | ftp://* | rsync://* )\n-\t\tfetch_dumb \"$@\"\n-\t\t;;\n-\t*)\n-\t\tfetch_native \"$@\"\n-\t\t;;\n-\tesac\n+\tif test \"$(get_data_source $remote_nick)\" = builtin; then\n+\t\tfetch_builtin \"$@\"\n+\telse\n+\t\tcase \"$remote\" in\n+\t\thttp://* | https://* | ftp://* | rsync://* )\n+\t\t\tfetch_dumb \"$@\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\tfetch_native \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\tfi\n }\n \n fetch_main \"$reflist\" || exit\n@@ -353,8 +362,7 @@ case \",$#,$remote_nick,\" in\n \tcurr_branch=$(git-symbolic-ref -q HEAD | sed -e 's|^refs/heads/||')\n \tmerge_branches=$(git-config \\\n \t\t--get-all \"branch.${curr_branch}.merge\" | sort -u)\n-\tfetch_branches=$(get_remote_default_refs_for_fetch -n $remote_nick |\n-\t\tsed -e 's/:.*$//g' -e 's/^+//' | sort -u)\n+\tfetch_branches=$(get_remote_fetch_branches $remote_nick)\n \ttest -n \"$merge_branches\" && test -n \"$fetch_branches\" &&\n \tmerge_branches=$(printf '%s\\n%s' \"$merge_branches\" \"$fetch_branches\" |\n \t\tsort | uniq -d)\ndiff --git a/git-parse-remote.sh b/git-parse-remote.sh\nindex 99e7184..4964810 100755\n--- a/git-parse-remote.sh\n+++ b/git-parse-remote.sh\n@@ -9,6 +9,9 @@ get_data_source () {\n \t*/*)\n \t\techo ''\n \t\t;;\n+\t.)\n+\t\techo builtin\n+\t\t;;\n \t*)\n \t\tif test \"$(git-config --get \"remote.$1.url\")\"\n \t\tthen\n@@ -31,6 +34,9 @@ get_remote_url () {\n \t'')\n \t\techo \"$1\"\n \t\t;;\n+\tbuiltin)\n+\t\techo \"$1\"\n+\t\t;;\n \tconfig)\n \t\tgit-config --get \"remote.$1.url\"\n \t\t;;\n@@ -57,7 +63,7 @@ get_default_remote () {\n get_remote_default_refs_for_push () {\n \tdata_source=$(get_data_source \"$1\")\n \tcase \"$data_source\" in\n-\t'' | branches)\n+\t'' | branches | builtin)\n \t\t;; # no default push mapping, just send matching refs.\n \tconfig)\n \t\tgit-config --get-all \"remote.$1.push\" ;;\n@@ -128,6 +134,8 @@ get_remote_default_refs_for_fetch () {\n \tcase \"$data_source\" in\n \t'')\n \t\tset explicit \"HEAD:\" ;;\n+\tbuiltin)\n+\t\tset explicit ;;\n \tconfig)\n \t\tset $(expand_refs_wildcard \"$1\" \\\n \t\t\t$(git-config --get-all \"remote.$1.fetch\")) ;;\n@@ -154,6 +162,18 @@ get_remote_default_refs_for_fetch () {\n \tfi\n }\n \n+# Returns list of sources\n+get_remote_fetch_branches () {\n+\tdata_source=$(get_data_source \"$1\")\n+\tcase \"$data_source\" in\n+\tbuiltin)\n+\t        git-show-ref | sed -n 's,.*[      ]refs/,refs/,p' ;;\n+\t*)\n+\t\tget_remote_default_refs_for_fetch -n \"$1\" | \\\n+\t\t\tsed -e 's/:.*$//g' -e 's/^+//' | sort -u ;;\n+\tesac\n+}\n+\n get_remote_refs_for_push () {\n \tcase \"$#\" in\n \t0) die \"internal error: get-remote-refs-for-push.\" ;;\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex 75c000a..9558bdb 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -145,9 +145,15 @@ test_expect_success 'test overriding tracking setup via --no-track' \\\n      git-config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n      (git-show-ref -q refs/remotes/local/master || git-fetch local) &&\n      git-branch --no-track my2 local/master &&\n+     git-config branch.autosetupmerge false &&\n      ! test $(git-config branch.my2.remote) = local &&\n      ! test $(git-config branch.my2.merge) = refs/heads/master'\n \n+test_expect_success 'test local tracking setup' \\\n+    'git branch --track my6 s &&\n+     test $(git-config branch.my6.remote) = . &&\n+     test $(git-config branch.my6.merge) = refs/heads/s'\n+\n # Keep this test last, as it changes the current branch\n cat >expect <<EOF\n 0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000\tbranch: Created from master\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 7eb3783..c424e5b 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -29,5 +29,18 @@ test_expect_success 'checking the results' '\n \tdiff file cloned/file\n '\n \n+test_expect_success 'test . as a remote' '\n+\n+\tgit branch copy master &&\n+\tgit config branch.copy.remote . &&\n+\tgit config branch.copy.merge refs/heads/master &&\n+\techo updated >file &&\n+\tgit commit -a -m updated &&\n+\tgit checkout copy &&\n+\ttest `cat file` = file &&\n+\tgit pull &&\n+\ttest `cat file` = updated\n+'\n+\n test_done\n \ndiff --git a/t/t9109-git-svn-pull.sh b/t/t9109-git-svn-pull.sh\nnew file mode 100755\nindex 0000000..4d59f60\n--- /dev/null\n+++ b/t/t9109-git-svn-pull.sh\n@@ -0,0 +1,31 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2007 Paolo Bonzini\n+#\n+\n+test_description='git-svn pull test'\n+. ./lib-git-svn.sh\n+\n+mkdir import\n+\n+cd import\n+\techo Hello World > motd\n+\tsvn import -m 'import for git-svn' . \"$svnrepo\" >/dev/null\n+cd ..\n+\n+test_expect_success 'initialize git-svn and fetch' \"\n+\tgit-svn init $svnrepo\n+\tgit-svn fetch\"\n+\n+svn co $svnrepo test_wc > /dev/null\n+cd test_wc\n+\techo Goodbye World > motd\n+\tsvn commit -m \"another svn commit\" > /dev/null\n+cd ..\n+\n+test_expect_success 'fetch and pull latest from svn' \\\n+\t'git-svn fetch &&\n+\t git pull . remotes/git-svn &&\n+\t grep Goodbye motd'\n+\n+test_done\n"},{"id":"37008","messageId":"87k5xlf6wp.fsf@gmail.com","threadId":"7206","inReplyTo":"45F69939.6070909@lu.unisi.ch","subject":"Re: [PATCH, fixed version] git-fetch, git-branch: Support local --track via a special remote `.'","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-03-13T16:24:38Z","receivedAt":"2007-03-13T16:24:38Z","isPatch":true,"sender":{"key":"santi@agolina.net","avatar":null},"body":"Paolo Bonzini <paolo.bonzini@lu.unisi.ch> writes:\n\nI've done it different, please see the mail:\n\nSubject: [PATCH 2/3] git-fetch: Support the local remote \".\"\n\nI've done it only modifying git-parse-remote.\n\n[...]\n\n>\n> \tThe failure, which I didn't see because I didn't have svn-perl\n> \tbindings installed, was caused by my usage of \"git-show-ref --heads\"\n> \twhere I should have used plain \"git-show-ref\".\n\nBut it should be test in t5515. I've added tests for this.\n\nThanks,\n\n  Santi\n"},{"id":"37077","messageId":"7vird4ax66.fsf@assigned-by-dhcp.cox.net","threadId":"7206","inReplyTo":"45F69939.6070909@lu.unisi.ch","subject":"Re: [PATCH, fixed version] git-fetch, git-branch: Support local --track via a special remote `.'","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2007-03-14T11:20:49Z","receivedAt":"2007-03-14T11:20:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Paolo Bonzini <paolo.bonzini@lu.unisi.ch> writes:\n\n>  t/t9109-git-svn-pull.sh  |   31 +++++++++++++++++++++++++++++++\n>  8 files changed, 120 insertions(+), 27 deletions(-)\n>\n> \tThe failure, which I didn't see because I didn't have svn-perl\n> \tbindings installed, was caused by my usage of \"git-show-ref --heads\"\n> \twhere I should have used plain \"git-show-ref\".\n>\n> \tI include a smaller testcase for the same problem, t9109.\n\nI'd prefer dropping the t9109 test, as it seems to be redundant.\nExisting t9101 seems to cover pulling from remote tracking\nbranch maintained by git-svn already.\n\nAlso I'll be reverting a couple of patches from 'next', so this\nno longer applies.  Would appreciate a re-spin.\n\nSorry about that.\n"},{"id":"37085","messageId":"45F7F011.5080308@lu.unisi.ch","threadId":"7206","inReplyTo":"7vird4ax66.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH, respin] git-fetch, git-branch: Support local --track via a special remote `.'","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@lu.unisi.ch","sentAt":"2007-03-14T12:52:33Z","receivedAt":"2007-03-14T12:52:33Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"This patch adds support for a dummy remote `.' to avoid having to declare\na fake remote like\n\n        [remote \"local\"]\n                url = .\n                fetch = refs/heads/*:refs/heads/*\n\nSuch a builtin remote simplifies the operation of \"git-fetch\", which\nwill populate FETCH_HEAD but will not pretend that two repositories are\nin use, will not create a thin pack, and will not perform any useless\nremapping of names.  The speed improvement is around 20%, and it should\nimprove more if \"git-fetch\" is converted to a builtin.\n\nTo this end, git-parse-remote is grown with a new kind of remote, `builtin'.\nIn git-fetch.sh, we treat the builtin remote specially in that it needs no\npack/store operations.  In fact, doing git-fetch on a builtin remote will\nsimply populate FETCH_HEAD appropriately.\n\nThe patch also improves of the --track/--no-track support, extending\nit so that branch.<name>.remote items referring `.' can be created.\nFinally, it fixes a typo in git-checkout.sh.\n\nSigned-off-by: Paolo Bonzini  <bonzini@gnu.org>\n---\n Documentation/config.txt |    4 ++++\n builtin-branch.c         |   39 +++++++++++++++++++++++++--------------\n git-checkout.sh          |    2 +-\n git-fetch.sh             |   28 ++++++++++++++++++++--------\n git-parse-remote.sh      |   12 ++++++++++--\n t/t3200-branch.sh        |    6 ++++++\n t/t5520-pull.sh          |   13 +++++++++++++\n 7 files changed, 79 insertions(+), 25 deletions(-)\n\n\t> I'd prefer dropping the t9109 test, as it seems to be redundant.\n\n\tAs you wish.\n\n\t> Also I'll be reverting a couple of patches from 'next', so this\n\t> no longer applies.  Would appreciate a re-spin.\n\t> \n\t> Sorry about that.\n\n\tNo problem.\n\n\tI must say that from a clarity point of view I preferred the\n\tolder code.  It did encapsulate fetching in a pretty easy to\n\tunderstand way.  OTOH, my patch is smaller now.\n\n\tJust my 0.02 cents, or something to remember once the\n\tgit-fetch--tool conversion proceeds and possibly the merge logic\n\tis written in C.\n\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex aaae9ac..953acae 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -272,6 +272,10 @@ branch.<name>.merge::\n \t`git fetch`) to lookup the default branch for merging. Without\n \tthis option, `git pull` defaults to merge the first refspec fetched.\n \tSpecify multiple values to get an octopus merge.\n+\tIf you wish to setup `git pull` so that it merges into <name> from\n+\tanother branch in the local repository, you can point\n+\tbranch.<name>.merge to the desired branch, and use the special setting\n+\t`.` (a period) for branch.<name>.remote.\n \n color.branch::\n \tA boolean to enable/disable color in the output of\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 42b1ff1..14c4219 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -372,9 +372,26 @@ static int get_remote_config(const char *key, const char *value)\n \treturn 0;\n }\n \n-static void set_branch_defaults(const char *name, const char *real_ref)\n+static void set_branch_merge(const char *name, const char *config_remote,\n+\t\t\t     const char *config_repo)\n {\n \tchar key[1024];\n+\tif (sizeof(key) <=\n+\t    snprintf(key, sizeof(key), \"branch.%s.remote\", name))\n+\t\tdie(\"what a long branch name you have!\");\n+\tgit_config_set(key, config_remote);\n+\n+\t/*\n+\t * We do not have to check if we have enough space for\n+\t * the 'merge' key, since it's shorter than the\n+\t * previous 'remote' key, which we already checked.\n+\t */\n+\tsnprintf(key, sizeof(key), \"branch.%s.merge\", name);\n+\tgit_config_set(key, config_repo);\n+}\n+\n+static void set_branch_defaults(const char *name, const char *real_ref)\n+{\n \tconst char *slash = strrchr(real_ref, '/');\n \n \tif (!slash)\n@@ -384,21 +401,15 @@ static void set_branch_defaults(const char *name, const char *real_ref)\n \tstart_len = strlen(real_ref);\n \tbase_len = slash - real_ref;\n \tgit_config(get_remote_config);\n+\tif (!config_repo && !config_remote &&\n+\t    !prefixcmp(real_ref, \"refs/heads/\")) {\n+\t\tset_branch_merge(name, \".\", real_ref);\n+\t\tprintf(\"Branch %s set up to track local branch %s.\\n\",\n+\t\t       name, real_ref);\n+\t}\n \n \tif (config_repo && config_remote) {\n-\t\tif (sizeof(key) <=\n-\t\t    snprintf(key, sizeof(key), \"branch.%s.remote\", name))\n-\t\t\tdie(\"what a long branch name you have!\");\n-\t\tgit_config_set(key, config_remote);\n-\n-\t\t/*\n-\t\t * We do not have to check if we have enough space for\n-\t\t * the 'merge' key, since it's shorter than the\n-\t\t * previous 'remote' key, which we already checked.\n-\t\t */\n-\t\tsnprintf(key, sizeof(key), \"branch.%s.merge\", name);\n-\t\tgit_config_set(key, config_repo);\n-\n+\t\tset_branch_merge(name, config_remote, config_repo);\n \t\tprintf(\"Branch %s set up to track remote branch %s.\\n\",\n \t\t       name, real_ref);\n \t}\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 6caa9fd..b292ff0 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -89,7 +89,7 @@ while [ \"$#\" != \"0\" ]; do\n     esac\n done\n \n-case \"$new_branch,$track\" in\n+case \"$newbranch,$track\" in\n ,--*)\n \tdie \"git checkout: --track and --no-track require -b\"\n esac\ndiff --git a/git-fetch.sh b/git-fetch.sh\nindex ebe6c33..88bf64d 100755\n--- a/git-fetch.sh\n+++ b/git-fetch.sh\n@@ -161,6 +161,14 @@ then\n \tfi\n fi\n \n+fetch_builtin () {\n+    for ref in $(get_remote_default_refs_for_fetch \"$remote_nick\"); do\n+      name=$(expr \"z$ref\" : 'z\\([^:]*\\):')\n+      append_fetch_head $(git-rev-parse \"$name\") \"$remote\" \\\n+\t  \"$name\" \"$remote_nick\" \"$name\" \"\" || exit\n+    done\n+}\n+\n fetch_native () {\n   eval=$(echo \"$1\" | git-fetch--tool parse-reflist \"-\")\n   eval \"$eval\"\n@@ -296,14 +303,18 @@ fetch_dumb () {\n }\n \n fetch_main () {\n-\tcase \"$remote\" in\n-\thttp://* | https://* | ftp://* | rsync://* )\n-\t\tfetch_dumb \"$@\"\n-\t\t;;\n-\t*)\n-\t\tfetch_native \"$@\"\n-\t\t;;\n-\tesac\n+\tif test \"$(get_data_source $remote_nick)\" = builtin; then\n+\t\tfetch_builtin\n+\telse\n+\t\tcase \"$remote\" in\n+\t\thttp://* | https://* | ftp://* | rsync://* )\n+\t\t\tfetch_dumb \"$@\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\tfetch_native \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\tfi\n }\n \n fetch_main \"$reflist\" || exit\ndiff --git a/git-parse-remote.sh b/git-parse-remote.sh\nindex c46131f..1b96ec6 100755\n--- a/git-parse-remote.sh\n+++ b/git-parse-remote.sh\n@@ -9,6 +9,9 @@ get_data_source () {\n \t*/*)\n \t\techo ''\n \t\t;;\n+\t.)\n+\t\techo builtin\n+\t\t;;\n \t*)\n \t\tif test \"$(git-config --get \"remote.$1.url\")\"\n \t\tthen\n@@ -31,6 +34,9 @@ get_remote_url () {\n \t'')\n \t\techo \"$1\"\n \t\t;;\n+\tbuiltin)\n+\t\techo \"$1\"\n+\t\t;;\n \tconfig)\n \t\tgit-config --get \"remote.$1.url\"\n \t\t;;\n@@ -57,7 +63,7 @@ get_default_remote () {\n get_remote_default_refs_for_push () {\n \tdata_source=$(get_data_source \"$1\")\n \tcase \"$data_source\" in\n-\t'' | branches)\n+\t'' | branches | builtin)\n \t\t;; # no default push mapping, just send matching refs.\n \tconfig)\n \t\tgit-config --get-all \"remote.$1.push\" ;;\n@@ -163,6 +169,8 @@ get_remote_default_refs_for_fetch () {\n \tcase \"$data_source\" in\n \t'')\n \t\techo \"HEAD:\" ;;\n+\tbuiltin)\n+\t        git-show-ref | sed -n 's,.*[      ]\\(refs/.*\\),\\1:,p' ;;\n \tconfig)\n \t\tcanon_refs_list_for_fetch -d \"$1\" \\\n \t\t\t$(git-config --get-all \"remote.$1.fetch\") ;;\n@@ -177,7 +185,7 @@ get_remote_default_refs_for_fetch () {\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+\t\tdie \"internal error: get-remote-default-ref-for-fetch $1\" ;;\n \tesac\n }\n \ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex 75c000a..9558bdb 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -145,9 +145,15 @@ test_expect_success 'test overriding tracking setup via --no-track' \\\n      git-config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n      (git-show-ref -q refs/remotes/local/master || git-fetch local) &&\n      git-branch --no-track my2 local/master &&\n+     git-config branch.autosetupmerge false &&\n      ! test $(git-config branch.my2.remote) = local &&\n      ! test $(git-config branch.my2.merge) = refs/heads/master'\n \n+test_expect_success 'test local tracking setup' \\\n+    'git branch --track my6 s &&\n+     test $(git-config branch.my6.remote) = . &&\n+     test $(git-config branch.my6.merge) = refs/heads/s'\n+\n # Keep this test last, as it changes the current branch\n cat >expect <<EOF\n 0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000\tbranch: Created from master\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 7eb3783..c424e5b 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -29,5 +29,17 @@ test_expect_success 'checking the results' '\n \tdiff file cloned/file\n '\n \n+test_expect_success 'test . as a remote' '\n+\tgit branch copy master &&\n+\tgit config branch.copy.remote . &&\n+\tgit config branch.copy.merge refs/heads/master &&\n+\techo updated >file &&\n+\tgit commit -a -m updated &&\n+\tgit checkout copy &&\n+\ttest `cat file` = file &&\n+\tgit pull &&\n+\ttest `cat file` = updated\n+'\n+\n test_done\n \n"}]}