{"thread":{"id":"10960","subject":"Wishlist for a bundle-only transport mode","startedAt":"2007-11-21T14:54:05Z","lastAt":"2007-11-24T19:15:19Z","messageCount":33,"participants":["Santi Béjar","Jakub Narebski","Johannes Schindelin","Kristian Høgsberg","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"60522","messageId":"8aa486160711210654p357ccd87i4809e0cda9471303@mail.gmail.com","threadId":"10960","inReplyTo":null,"subject":"Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-21T14:54:05Z","receivedAt":"2007-11-21T14:54:05Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"Hi *,\n\n  I have to work in a bundle-only mode, but there are some problems\nwith it, namely:\n\n1) git-clone does not accept a bundle file, even if git-fetch does.\nI've made a patch to use git-fetch in git-clone for this.\n\n2) The bundles created with \"git bundle\" does not record the HEAD,\nthey resolve the symbolic name to a branch name.\n\n3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n\n[remote \"bundle\"]\n  url = /file/to/bundle\n  fetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n\n$ git push bundle\n\nwould create a bundle in /file/to/bundle with the same branches as a\nnormal git push, but considering the remote branches as the local\nremotes/bundle/*\n\nThank you\n\nSanti\n"},{"id":"60524","messageId":"fi1heo$u4i$1@ger.gmane.org","threadId":"10960","inReplyTo":"8aa486160711210654p357ccd87i4809e0cda9471303@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-21T15:04:57Z","receivedAt":"2007-11-21T15:04:57Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Santi Béjar wrote:\n\n> 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n> \n> [remote \"bundle\"]\n>   url = /file/to/bundle\n>   fetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n> \n> $ git push bundle\n> \n> would create a bundle in /file/to/bundle with the same branches as a\n> normal git push, but considering the remote branches as the local\n> remotes/bundle/*\n\nAnd how you would differentiate between path meaning bundle, and\npath meaning \"local\" protocol, i.e. git repository on the same\nfilesystem? \"bundle = /file/to/bundle\" perhaps...\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"60527","messageId":"8aa486160711210724s2cad1e05s15360d03a77d8cac@mail.gmail.com","threadId":"10960","inReplyTo":"fi1heo$u4i$1@ger.gmane.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-21T15:24:42Z","receivedAt":"2007-11-21T15:24:42Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Nov 21, 2007 4:04 PM, Jakub Narebski <jnareb@gmail.com> wrote:\n> Santi Béjar wrote:\n>\n> > 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n> >\n> > [remote \"bundle\"]\n> > url = /file/to/bundle\n> > fetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n> >\n> > $ git push bundle\n> >\n> > would create a bundle in /file/to/bundle with the same branches as a\n> > normal git push, but considering the remote branches as the local\n> > remotes/bundle/*\n>\n> And how you would differentiate between path meaning bundle, and\n> path meaning \"local\" protocol, i.e. git repository on the same\n> filesystem? \"bundle = /file/to/bundle\" perhaps...\n\nGood point. The git repository must exist before pushing, but the bundle:\n\n1) Exist and is a file, do nothing by default, maybe requiere a --overwrite\n2) Does not exist, create the bundle, but maybe you've written badly the url, so\n    the best thing would be to say explicitly that you wanted a bundle\nlike you said.\n\nSanti\n"},{"id":"60529","messageId":"Pine.LNX.4.64.0711211544510.27959@racer.site","threadId":"10960","inReplyTo":"fi1heo$u4i$1@ger.gmane.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T15:46:03Z","receivedAt":"2007-11-21T15:46:03Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Jakub Narebski wrote:\n\n> Santi B?jar wrote:\n> \n> > 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n> > \n> > [remote \"bundle\"]\n> > ? url = /file/to/bundle\n> > ? fetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n> > \n> > $ git push bundle\n> > \n> > would create a bundle in /file/to/bundle with the same branches as a\n> > normal git push, but considering the remote branches as the local\n> > remotes/bundle/*\n> \n> And how you would differentiate between path meaning bundle, and path \n> meaning \"local\" protocol, i.e. git repository on the same filesystem? \n\nMaybe because the git repository is specified as an existing directory?  \nThe bundle is specified as a (possibly non-existing) file...\n\nHth,\nDscho\n"},{"id":"60533","messageId":"Pine.LNX.4.64.0711211554370.27959@racer.site","threadId":"10960","inReplyTo":"8aa486160711210654p357ccd87i4809e0cda9471303@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T15:59:51Z","receivedAt":"2007-11-21T15:59:51Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Santi B?jar wrote:\n\n> 1) git-clone does not accept a bundle file, even if git-fetch does. I've \n> made a patch to use git-fetch in git-clone for this.\n\nThis, along with rewriting git-clone as a very thin wrapper over git-init, \n-remote and -fetch, is a really low hanging fruit.\n\nOr maybe go the full nine yards and build it in.  Should be a breeze now, \ngiven parse_options() and run_command().\n\n> 2) The bundles created with \"git bundle\" does not record the HEAD, they \n> resolve the symbolic name to a branch name.\n\nIt imitates ls-remote output.\n\n> 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n> \n> [remote \"bundle\"]\n>   url = /file/to/bundle\n>   fetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n> \n> $ git push bundle\n> \n> would create a bundle in /file/to/bundle with the same branches as a\n> normal git push, but considering the remote branches as the local\n> remotes/bundle/*\n\nDoes not seem to be too complicated to add it to transport.c IMHO.  \nSomething similar to rsync_transport_push().  And I'd definitely refuse to \noverwrite any existing file.\n\nCiao,\nDscho\n"},{"id":"60536","messageId":"8aa486160711210815g5a1973c2see28a6263fc56030@mail.gmail.com","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211554370.27959@racer.site","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-21T16:15:35Z","receivedAt":"2007-11-21T16:15:35Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Nov 21, 2007 4:59 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Wed, 21 Nov 2007, Santi B?jar wrote:\n>\n> > 1) git-clone does not accept a bundle file, even if git-fetch does. I've\n> > made a patch to use git-fetch in git-clone for this.\n>\n> This, along with rewriting git-clone as a very thin wrapper over git-init,\n> -remote and -fetch, is a really low hanging fruit.\n\nFor the basic/normal mode it can be a very thin wrapper but you have\nto support --local, --shared, --reference...\n\n> > 2) The bundles created with \"git bundle\" does not record the HEAD, they\n> > resolve the symbolic name to a branch name.\n>\n> It imitates ls-remote output.\n\nNo, it does not.\n\nWith a newly created project with one commit:\n\n$ git ls-remote git.git\nb71992713c17c3a29f9566e1b50e8cf402375faf        HEAD\nb71992713c17c3a29f9566e1b50e8cf402375faf        refs/heads/master\n\n$ git bundle create git.bdl HEAD master\n\n$ git bundle list-heads git.bdl\nb71992713c17c3a29f9566e1b50e8cf402375faf refs/heads/master\nb71992713c17c3a29f9566e1b50e8cf402375faf refs/heads/master\n\nSanti\n"},{"id":"60538","messageId":"1195662180.28318.19.camel@hinata.boston.redhat.com","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211554370.27959@racer.site","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-11-21T16:23:00Z","receivedAt":"2007-11-21T16:23:00Z","isPatch":false,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Wed, 2007-11-21 at 15:59 +0000, Johannes Schindelin wrote:\n> Hi,\n> \n> On Wed, 21 Nov 2007, Santi B?jar wrote:\n> \n> > 1) git-clone does not accept a bundle file, even if git-fetch does. I've \n> > made a patch to use git-fetch in git-clone for this.\n> \n> This, along with rewriting git-clone as a very thin wrapper over git-init, \n> -remote and -fetch, is a really low hanging fruit.\n> \n> Or maybe go the full nine yards and build it in.  Should be a breeze now, \n> given parse_options() and run_command().\n\nI started doing this, which is pretty stupid as I'm pressed to find time\nto finish up builtin-commit.  Nevertheless, could you elaborate on the\nplan here?  How would you rewrite it to just use remote and fetch?  I\njust finished the boilerplate option parsing stuff (patch below) and\nstarted reading the core of git-clone.sh, but if most of this can be\nreplaced I'd like to hear about it :)\n\ncheers,\nKristian\n\n>From ccfa6b7b6c0bad98201166db3f91760b423ab0c9 Mon Sep 17 00:00:00 2001\nFrom: =?utf-8?q?Kristian=20H=C3=B8gsberg?= <krh@redhat.com>\nDate: Sun, 18 Nov 2007 18:48:04 -0500\nSubject: [PATCH] builtin-clone: first steps, up to and including\ngit-init.\n\n---\n Makefile                                      |    2 +-\n builtin-clone.c                               |  286\n+++++++++++++++++++++++++\n builtin-init-db.c                             |   90 ++++----\n builtin.h                                     |    1 +\n cache.h                                       |    4 +\n git-clone.sh => contrib/examples/git-clone.sh |    0 \n git.c                                         |    1 +\n 7 files changed, 341 insertions(+), 43 deletions(-)\n create mode 100644 builtin-clone.c\n rename git-clone.sh => contrib/examples/git-clone.sh (100%)\n\ndiff --git a/Makefile b/Makefile\nindex 4d23d12..f39b7e8 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -213,7 +213,6 @@ BASIC_LDFLAGS =\n \n SCRIPT_SH = \\\n \tgit-bisect.sh git-checkout.sh \\\n-\tgit-clone.sh \\\n \tgit-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \\\n \tgit-pull.sh git-rebase.sh git-rebase--interactive.sh \\\n \tgit-repack.sh git-request-pull.sh \\\n@@ -327,6 +326,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-checkout-index.o \\\n \tbuiltin-check-ref-format.o \\\n \tbuiltin-clean.o \\\n+\tbuiltin-clone.o \\\n \tbuiltin-commit.o \\\n \tbuiltin-commit-tree.o \\\n \tbuiltin-count-objects.o \\\ndiff --git a/builtin-clone.c b/builtin-clone.c\nnew file mode 100644\nindex 0000000..8a569e0\n--- /dev/null\n+++ b/builtin-clone.c\n@@ -0,0 +1,286 @@\n+/*\n+ * Builtin \"git clone\"\n+ *\n+ * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>\n+ * Based on git-commit.sh by Junio C Hamano and Linus Torvalds\n+ *\n+ * Clone a repository into a different directory that does not yet\nexist.\n+ */\n+\n+#include \"cache.h\"\n+#include \"parse-options.h\"\n+\n+/*\n+ * Implementation notes:\n+ *  - dropping use-separate-remote and no-separate-remote compatibility\n+ *\n+ */\n+static const char * const builtin_clone_usage[] = {\n+\t\"git-clone [options] [--] <repo> [<dir>]\",\n+\tNULL\n+};\n+\n+static int option_quiet, option_no_checkout, option_bare;\n+static int option_local, option_no_hardlinks, option_shared,\noption_depth;\n+static char *option_template, *option_reference, *option_origin;\n+static char *option_upload_pack;\n+\n+static struct option builtin_clone_options[] = {\n+\tOPT__QUIET(&option_quiet),\n+\tOPT_BOOLEAN('n', \"no-checkout\", &option_no_checkout,\n+\t\t    \"don't create a checkout\"),\n+\tOPT_BOOLEAN(0, \"bare\", &option_bare, \"create a bare repository\"),\n+\tOPT_BOOLEAN(0, \"naked\", &option_bare, \"create a bare repository\"),\n+\tOPT_BOOLEAN('l', \"local\", &option_local,\n+\t\t    \"to clone from a local repository\"),\n+\tOPT_BOOLEAN(0, \"no-hardlinks\", &option_no_hardlinks,\n+\t\t    \"don't use local hardlinks, always copy\"),\n+\tOPT_BOOLEAN('s', \"shared\", &option_shared,\n+\t\t    \"setup as shared repository\"),\n+\tOPT_STRING(0, \"template\", &option_template, \"path\",\n+\t\t   \"path the template repository\"),\n+\tOPT_STRING(0, \"reference\", &option_reference, \"repo\",\n+\t\t   \"reference repository\"),\n+\tOPT_STRING('o', \"origin\", &option_origin, \"branch\",\n+\t\t   \"use <branch> instead or 'origin' to track upstream\"),\n+\tOPT_STRING('u', \"upload-pack\", &option_upload_pack, \"path\",\n+\t\t   \"path to git-upload-pack on the remote\"),\n+\tOPT_INTEGER(0, \"depth\", &option_depth,\n+\t\t    \"create a shallow clone of that depth\"),\n+\n+\tOPT_END()\n+};\n+\n+static char *get_repo_path(const char *repo)\n+{\n+\tconst char *path;\n+\tstruct stat buf;\n+\n+\tpath = mkpath(\"%s/.git\", repo);\n+\tif (!stat(path, &buf) && S_ISDIR(buf.st_mode))\n+\t\treturn xstrdup(make_absolute_path(path));\n+\n+\tpath = mkpath(\"%s.git\", repo);\n+\tif (!stat(path, &buf) && S_ISDIR(buf.st_mode))\n+\t\treturn xstrdup(make_absolute_path(path));\n+\n+\tif (!stat(repo, &buf) && S_ISDIR(buf.st_mode))\n+\t\treturn xstrdup(make_absolute_path(repo));\n+\t\n+\treturn NULL;\n+}\n+\n+static char *guess_dir_name(const char *repo)\n+{\n+\tconst char *p, *start, *end, *limit;\n+\tint after_slash_or_colon;\n+\n+\t/* Guess dir name from repository: strip trailing '/',\n+\t * strip trailing '[:/]*git', strip leading '.*[/:]'. */\n+\n+\tafter_slash_or_colon = 1;\n+\tlimit = repo + strlen(repo);\n+\tstart = repo;\n+\tend = limit;\n+\tfor (p = repo; p < limit; p++) {\n+\t\tif (!prefixcmp(p, \".git\")) {\n+\t\t\tif (!after_slash_or_colon)\n+\t\t\t\tend = p;\n+\t\t\tp += 3;\n+\t\t} else if (*p == '/' || *p == ':') {\n+\t\t\tif (end == limit)\n+\t\t\t\tend = p; \n+\t\t\tafter_slash_or_colon = 1;\n+\t\t} else if (after_slash_or_colon) {\n+\t\t\tstart = p;\n+\t\t\tend = limit;\n+\t\t\tafter_slash_or_colon = 0;\n+\t\t}\n+\t}\n+\n+\treturn xstrndup(start, end - start);\n+}\n+\n+static void\n+setup_reference(void)\n+{\n+\tstruct stat buf;\n+\tconst char *ref_git, *alternates;\n+\tint fd;\n+\n+\tif (!option_reference)\n+\t\treturn;\n+\n+\tif (!stat(mkpath(\"%s/.git/objects\", option_reference), &buf) &&\n+\t    S_ISDIR(buf.st_mode))\n+\t\tref_git = mkpath(\"%s/.git\", option_reference);\n+\telse if (!stat(mkpath(\"%s/objects\", option_reference), &buf) &&\n+\t\t S_ISDIR(buf.st_mode))\n+\t\tref_git = option_reference;\n+\telse\n+\t\tdie(\"reference repository '%s' is not a local directory.\",\n+\t\t    option_reference);\n+\n+\tref_git = make_absolute_path(ref_git);\n+\t\n+\tfd = open(git_path(\"objects/info/alternates\"),\n+\t\t  O_WRONLY | O_CREAT, 0666);\n+\tif (fd < 0)\n+\t\tdie(\"could not create alternates file\\n\");\n+\talternates = mkpath(\"%s/objects\\n\", ref_git);\n+\twrite_or_die(fd, alternates, strlen(alternates));\n+\tif (close(fd) < 0)\n+\t\tdie(\"could not close alternates file\\n\");\n+\n+\t/* This part is going to be tricky, since it deals with two\n+\t * repositories.  Most code in git works on global state\n+\t * assumed to be coming from the one active repository, but\n+\t * here we want to do for-each-ref in one repository and say\n+\t * update-ref in another.  We could just say set_git_dir() and\n+\t * then say for-each-ref and store the refs in an array and\n+\t * the say set_git_dir() again to switch to the repository\n+\t * we're creating and then write out the refs using update-ref. */\n+\n+\t/*\n+\n+\techo \"$ref_git/objects\" >\"$GIT_DIR/objects/info/alternates\"\n+\t(\n+\t\tGIT_DIR=\"$ref_git\" git for-each-ref \\\n+\t\t\t--format='%(objectname) %(*objectname)'\n+\t) |\n+\twhile read a b\n+\tdo\n+\t\ttest -z \"$a\" ||\n+\t\tgit update-ref \"refs/reference-tmp/$a\" \"$a\"\n+\t\ttest -z \"$b\" ||\n+\t\tgit update-ref \"refs/reference-tmp/$b\" \"$b\"\n+\tdone\n+\n+\t*/\n+}\n+\n+static void\n+cleanup_reference(void)\n+{\n+\t/*\n+\t  test -d \"$GIT_DIR/refs/reference-tmp\" &&\n+\t\trm -fr \"$GIT_DIR/refs/reference-tmp\"\n+\t*/\n+}\n+\n+static void\n+clone_local(const char *path)\n+{\n+\t/* local hardlink magic */\n+\tprintf(\"local, from %s\\n\", path);\n+}\n+\n+static void\n+clone_rsync(const char *repo)\n+{\n+\tprintf(\"rsync, from %s\\n\", repo);\n+\tif (option_depth > 0)\n+\t\tdie(\"shallow over rsync not supported\");\n+}\n+\n+static void\n+clone_native(const char *repo)\n+{\n+\t\tprintf(\"native git, from %s\\n\", repo);\n+}\n+\n+static void\n+clone_curl(const char *repo)\n+{\n+\tprintf(\"curl, from %s\\n\", repo);\n+\tif (option_depth > 0)\n+\t\tdie(\"shallow over rsync not supported\");\n+}\n+\n+int cmd_clone(int argc, const char **argv, const char *prefix)\n+{\n+\tint use_local_hardlinks = 1;\n+\tint use_separate_remote = 1;\n+\tstruct stat buf;\n+\tconst char *repo, *work_tree, *git_dir;\n+\tchar *path, *dir;\n+\n+\targc = parse_options(argc, argv, builtin_clone_options,\n+\t\t\t     builtin_clone_usage, 0);\n+\n+\tif (argc == 0)\n+\t\tdie(\"You must specify a repository to clone.\");\n+\n+\tif (option_no_hardlinks)\n+\t\tuse_local_hardlinks = 0;\n+\n+\tif (option_bare) {\n+\t\tif (option_origin)\n+\t\t\tdie(\"--bare and --origin %s options are incompatible.\",\n+\t\t\t    option_origin);\n+\t\toption_no_checkout = 1;\n+\t\tuse_separate_remote = 0;\n+\t}\n+\n+\tif (!option_origin)\n+\t\toption_origin = \"origin\";\n+\n+\trepo = argv[0];\n+\tpath = get_repo_path(repo);\n+\n+\tif (argc == 2) {\n+\t\tdir = xstrdup(argv[1]);\n+\t} else {\n+\t\tdir = guess_dir_name(repo);\n+\t}\n+\n+\tprintf(\"repo: %s, path: %s\\n\", repo, path);\n+\tprintf(\"dir: %s\\n\", dir);\n+\n+\tif (!stat(dir, &buf))\n+\t\tdie(\"destination directory '%s' already exists.\", dir);\n+\n+\tif (option_bare)\n+\t\twork_tree = NULL;\n+\telse {\n+\t\twork_tree = getenv(\"GIT_WORK_TREE\");\n+\t\tif (work_tree && !stat(work_tree, &buf))\n+\t\t\tdie(\"working tree '%s' already exists.\", work_tree);\n+\t}\n+\n+\tif (mkdir(dir, 0755))\n+\t\tdie(\"could not create repository dir '%s'.\", dir);\n+\tif (work_tree && mkdir(work_tree, 0755))\n+\t\tdie(\"could not create work tree dir '%s'.\", work_tree);\n+\n+\tif (option_bare || work_tree)\n+\t\tgit_dir = xstrdup(dir); \n+\telse\n+\t\tgit_dir = xstrdup(mkpath(\"%s/.git\", dir));\n+\n+\tset_git_dir(make_absolute_path(git_dir));\n+\tinit_db(git_dir, option_template, option_quiet ? INIT_DB_QUIET : 0);\n+\n+\tif (option_bare)\n+\t\tgit_config_set(\"core.bare\", \"true\");\n+\n+\tsetup_reference();\n+\n+\tif (path != NULL) {\n+\t\tclone_local(path);\n+\t} else if (!prefixcmp(repo, \"rsync://\")) {\n+\t\tclone_rsync(repo);\n+\t} else if (!prefixcmp(repo, \"https://\") ||\n+\t\t   !prefixcmp(repo, \"http://\") ||\n+\t\t   !prefixcmp(repo, \"ftp://\")) {\n+\t\tclone_curl(repo);\n+\t} else {\n+\t\tclone_native(repo);\n+\t}\n+\n+\tcleanup_reference();\n+\n+\n+\n+\treturn 0;\n+}\ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex e1393b8..0ddfb46 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -330,49 +330,11 @@ static void guess_repository_type(const char\n*git_dir)\n \treturn;\n }\n \n-static const char init_db_usage[] =\n-\"git-init [-q | --quiet] [--template=<template-directory>] [--shared]\";\n-\n-/*\n- * If you want to, you can share the DB area with any number of\nbranches.\n- * That has advantages: you can save space by sharing all the SHA1\nobjects.\n- * On the other hand, it might just make lookup slower and messier. You\n- * be the judge.  The default case is to have one DB per managed\ndirectory.\n- */\n-int cmd_init_db(int argc, const char **argv, const char *prefix)\n+int init_db(const char *git_dir, const char *template_dir, unsigned int\nflags)\n {\n-\tconst char *git_dir;\n \tconst char *sha1_dir;\n-\tconst char *template_dir = NULL;\n \tchar *path;\n-\tint len, i, reinit;\n-\tint quiet = 0;\n-\n-\tfor (i = 1; i < argc; i++, argv++) {\n-\t\tconst char *arg = argv[1];\n-\t\tif (!prefixcmp(arg, \"--template=\"))\n-\t\t\ttemplate_dir = arg+11;\n-\t\telse if (!strcmp(arg, \"--shared\"))\n-\t\t\tshared_repository = PERM_GROUP;\n-\t\telse if (!prefixcmp(arg, \"--shared=\"))\n-\t\t\tshared_repository = git_config_perm(\"arg\", arg+9);\n-\t\telse if (!strcmp(arg, \"-q\") || !strcmp(arg, \"--quiet\"))\n-\t\t        quiet = 1;\n-\t\telse\n-\t\t\tusage(init_db_usage);\n-\t}\n-\n-\t/*\n-\t * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR\n-\t * without --bare.  Catch the error early.\n-\t */\n-\tgit_dir = getenv(GIT_DIR_ENVIRONMENT);\n-\tif ((!git_dir || is_bare_repository_cfg == 1)\n-\t    && getenv(GIT_WORK_TREE_ENVIRONMENT))\n-\t\tdie(\"%s (or --work-tree=<directory>) not allowed without \"\n-\t\t    \"specifying %s (or --git-dir=<directory>)\",\n-\t\t    GIT_WORK_TREE_ENVIRONMENT,\n-\t\t    GIT_DIR_ENVIRONMENT);\n+\tint len, reinit;\n \n \tguess_repository_type(git_dir);\n \n@@ -388,7 +350,6 @@ int cmd_init_db(int argc, const char **argv, const\nchar *prefix)\n \t/*\n \t * Set up the default .git directory contents\n \t */\n-\tgit_dir = getenv(GIT_DIR_ENVIRONMENT);\n \tif (!git_dir)\n \t\tgit_dir = DEFAULT_GIT_DIR_ENVIRONMENT;\n \tsafe_create_dir(git_dir, 0);\n@@ -427,7 +388,7 @@ int cmd_init_db(int argc, const char **argv, const\nchar *prefix)\n \t\tgit_config_set(\"receive.denyNonFastforwards\", \"true\");\n \t}\n \n-\tif (!quiet)\n+\tif (!(flags & INIT_DB_QUIET))\n \t\tprintf(\"%s%s Git repository in %s/\\n\",\n \t\t       reinit ? \"Reinitialized existing\" : \"Initialized empty\",\n \t\t       shared_repository ? \" shared\" : \"\",\n@@ -435,3 +396,48 @@ int cmd_init_db(int argc, const char **argv, const\nchar *prefix)\n \n \treturn 0;\n }\n+\n+static const char init_db_usage[] =\n+\"git-init [-q | --quiet] [--template=<template-directory>] [--shared]\";\n+\n+/*\n+ * If you want to, you can share the DB area with any number of\nbranches.\n+ * That has advantages: you can save space by sharing all the SHA1\nobjects.\n+ * On the other hand, it might just make lookup slower and messier. You\n+ * be the judge.  The default case is to have one DB per managed\ndirectory.\n+ */\n+int cmd_init_db(int argc, const char **argv, const char *prefix)\n+{\n+\tconst char *git_dir;\n+\tconst char *template_dir = NULL;\n+\tunsigned int flags = 0;\n+\tint i;\n+\n+\tfor (i = 1; i < argc; i++, argv++) {\n+\t\tconst char *arg = argv[1];\n+\t\tif (!prefixcmp(arg, \"--template=\"))\n+\t\t\ttemplate_dir = arg+11;\n+\t\telse if (!strcmp(arg, \"--shared\"))\n+\t\t\tshared_repository = PERM_GROUP;\n+\t\telse if (!prefixcmp(arg, \"--shared=\"))\n+\t\t\tshared_repository = git_config_perm(\"arg\", arg+9);\n+\t\telse if (!strcmp(arg, \"-q\") || !strcmp(arg, \"--quiet\"))\n+\t\t        flags |= INIT_DB_QUIET;\n+\t\telse\n+\t\t\tusage(init_db_usage);\n+\t}\n+\n+\t/*\n+\t * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR\n+\t * without --bare.  Catch the error early.\n+\t */\n+\tgit_dir = getenv(GIT_DIR_ENVIRONMENT);\n+\tif ((!git_dir || is_bare_repository_cfg == 1)\n+\t    && getenv(GIT_WORK_TREE_ENVIRONMENT))\n+\t\tdie(\"%s (or --work-tree=<directory>) not allowed without \"\n+\t\t    \"specifying %s (or --git-dir=<directory>)\",\n+\t\t    GIT_WORK_TREE_ENVIRONMENT,\n+\t\t    GIT_DIR_ENVIRONMENT);\n+\n+\treturn init_db(git_dir, template_dir, flags);\n+}\ndiff --git a/builtin.h b/builtin.h\nindex 6f01e96..8e59778 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -24,6 +24,7 @@ extern int cmd_check_attr(int argc, const char **argv,\nconst char *prefix);\n extern int cmd_check_ref_format(int argc, const char **argv, const char\n*prefix);\n extern int cmd_cherry(int argc, const char **argv, const char *prefix);\n extern int cmd_cherry_pick(int argc, const char **argv, const char\n*prefix);\n+extern int cmd_clone(int argc, const char **argv, const char *prefix);\n extern int cmd_clean(int argc, const char **argv, const char *prefix);\n extern int cmd_commit(int argc, const char **argv, const char *prefix);\n extern int cmd_commit_tree(int argc, const char **argv, const char\n*prefix);\ndiff --git a/cache.h b/cache.h\nindex 510154b..8c5f6af 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -230,6 +230,10 @@ extern const char *prefix_filename(const char\n*prefix, int len, const char *path\n extern void verify_filename(const char *prefix, const char *name);\n extern void verify_non_filename(const char *prefix, const char *name);\n \n+#define INIT_DB_QUIET 0x0001\n+\n+extern int init_db(const char *git_dir, const char *template_dir,\nunsigned int flags);\n+\n #define alloc_nr(x) (((x)+16)*3/2)\n \n /*\ndiff --git a/git-clone.sh b/contrib/examples/git-clone.sh\nsimilarity index 100%\nrename from git-clone.sh\nrename to contrib/examples/git-clone.sh\ndiff --git a/git.c b/git.c\nindex 9606937..9236833 100644\n--- a/git.c\n+++ b/git.c\n@@ -293,6 +293,7 @@ static void handle_internal_command(int argc, const\nchar **argv)\n \t\t{ \"check-attr\", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"cherry\", cmd_cherry, RUN_SETUP },\n \t\t{ \"cherry-pick\", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },\n+\t\t{ \"clone\", cmd_clone },\n \t\t{ \"clean\", cmd_clean, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n-- \n1.5.3.4\n"},{"id":"60539","messageId":"Pine.LNX.4.64.0711211632090.27959@racer.site","threadId":"10960","inReplyTo":"8aa486160711210815g5a1973c2see28a6263fc56030@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T16:36:33Z","receivedAt":"2007-11-21T16:36:33Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Santi B?jar wrote:\n\n> On Nov 21, 2007 4:59 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n>\n> > On Wed, 21 Nov 2007, Santi B?jar wrote:\n> >\n> > > 1) git-clone does not accept a bundle file, even if git-fetch does. \n> > > I've made a patch to use git-fetch in git-clone for this.\n> >\n> > This, along with rewriting git-clone as a very thin wrapper over \n> > git-init, -remote and -fetch, is a really low hanging fruit.\n> \n> For the basic/normal mode it can be a very thin wrapper but you have to \n> support --local, --shared, --reference...\n\nThat is not all that difficult.\n\n> > > 2) The bundles created with \"git bundle\" does not record the HEAD, \n> > > they resolve the symbolic name to a branch name.\n> >\n> > It imitates ls-remote output.\n> \n> No, it does not.\n> \n> With a newly created project with one commit:\n> \n> $ git ls-remote git.git\n> b71992713c17c3a29f9566e1b50e8cf402375faf        HEAD\n> b71992713c17c3a29f9566e1b50e8cf402375faf        refs/heads/master\n> \n> $ git bundle create git.bdl HEAD master\n> \n> $ git bundle list-heads git.bdl\n> b71992713c17c3a29f9566e1b50e8cf402375faf refs/heads/master\n> b71992713c17c3a29f9566e1b50e8cf402375faf refs/heads/master\n\nAh, I misunderstood.  I thought you were expecting that the first line \nwould read\n\n\trefs/heads/master\tHEAD\n\nAlas, this behaviour stems from dwim_ref() returning \"refs/heads/master\" \nas real ref.\n\nI am not quite sure how to solve this, though.  Let me see what I can come \nup with.\n\nCiao,\nDscho\n \n"},{"id":"60540","messageId":"8aa486160711210844jf412bb2pd09aa207ff62f08f@mail.gmail.com","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211632090.27959@racer.site","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-21T16:44:49Z","receivedAt":"2007-11-21T16:44:49Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Nov 21, 2007 5:36 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Wed, 21 Nov 2007, Santi B?jar wrote:\n>\n> > On Nov 21, 2007 4:59 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> >\n> > > On Wed, 21 Nov 2007, Santi B?jar wrote:\n> > >\n> > > > 1) git-clone does not accept a bundle file, even if git-fetch does.\n> > > > I've made a patch to use git-fetch in git-clone for this.\n> > >\n> > > This, along with rewriting git-clone as a very thin wrapper over\n> > > git-init, -remote and -fetch, is a really low hanging fruit.\n> >\n> > For the basic/normal mode it can be a very thin wrapper but you have to\n> > support --local, --shared, --reference...\n>\n> That is not all that difficult.\n\nI did not say it was difficult, I said it was not a very thin wrapper.\n\n>\n> > > > 2) The bundles created with \"git bundle\" does not record the HEAD,\n> > > > they resolve the symbolic name to a branch name.\n> > >\n> > > It imitates ls-remote output.\n> >\n> > No, it does not.\n> >\n> > With a newly created project with one commit:\n> >\n> > $ git ls-remote git.git\n> > b71992713c17c3a29f9566e1b50e8cf402375faf        HEAD\n> > b71992713c17c3a29f9566e1b50e8cf402375faf        refs/heads/master\n> >\n> > $ git bundle create git.bdl HEAD master\n> >\n> > $ git bundle list-heads git.bdl\n> > b71992713c17c3a29f9566e1b50e8cf402375faf refs/heads/master\n> > b71992713c17c3a29f9566e1b50e8cf402375faf refs/heads/master\n>\n> Ah, I misunderstood.\n\nMaybe because of my non-native english :-)\n\n>  I thought you were expecting that the first line\n> would read\n>\n>         refs/heads/master       HEAD\n\nor\n\nref: refs/heads/master        HEAD\n\nThat would be perfect, but it is a different story.\n\n>\n> Alas, this behaviour stems from dwim_ref() returning \"refs/heads/master\"\n> as real ref.\n>\n> I am not quite sure how to solve this, though.  Let me see what I can come\n> up with.\n\nThank you.\n\nSanti\n"},{"id":"60541","messageId":"200711211752.40264.jnareb@gmail.com","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211544510.27959@racer.site","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-21T16:52:39Z","receivedAt":"2007-11-21T16:52:39Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Johannes Schindelin wrote:\n> On Wed, 21 Nov 2007, Jakub Narebski wrote:\n>> Santi Bejar wrote:\n>> \n>>> 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n>>> \n>>> [remote \"bundle\"]\n>>> \turl = /file/to/bundle\n>>> \tfetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n>>> \n>>> $ git push bundle\n>>> \n>>> would create a bundle in /file/to/bundle with the same branches as a\n>>> normal git push, but considering the remote branches as the local\n>>> remotes/bundle/*\n>> \n>> And how you would differentiate between path meaning bundle, and path \n>> meaning \"local\" protocol, i.e. git repository on the same filesystem? \n> \n> Maybe because the git repository is specified as an existing directory?  \n> The bundle is specified as a (possibly non-existing) file...\n\nThat has the disadvantage of pushing to bundle when you make an error\nin the lastpart of path to existing repository.\n\nAfter thinking about it a bit, I think it would be better to use \nbundle:// pseudoprotocol for the URL including config (bundle://file,\nbundle:///path/to/bundle) and --bundle option to git push for\ncommandline.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"60542","messageId":"Pine.LNX.4.64.0711211652470.27959@racer.site","threadId":"10960","inReplyTo":"8aa486160711210815g5a1973c2see28a6263fc56030@mail.gmail.com","subject":"[PATCH] bundle create: keep symbolic refs' names instead of resolving them","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T16:53:12Z","receivedAt":"2007-11-21T16:53:12Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhen creating a bundle, symbolic refs used to be resolved to the\nnon-symbolic refs they point to before being written to the list\nof contained refs.  I.e. \"git bundle create a1.bundle HEAD master\"\nwould show something like\n\n388afe7881b33102fada216dd07806728773c011        refs/heads/master\n388afe7881b33102fada216dd07806728773c011        refs/heads/master\n\nIntroduce a special handling so that the symbolic refs are listed\nwith the names passed on the command line.\n\nNoticed by Santi Béjar.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n bundle.c |   13 ++++++++-----\n 1 files changed, 8 insertions(+), 5 deletions(-)\n\ndiff --git a/bundle.c b/bundle.c\nindex e4d60cd..5e8242f 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -6,6 +6,7 @@\n #include \"revision.h\"\n #include \"list-objects.h\"\n #include \"run-command.h\"\n+#include \"refs.h\"\n \n static const char bundle_signature[] = \"# v2 git bundle\\n\";\n \n@@ -231,12 +232,17 @@ int create_bundle(struct bundle_header *header, const char *path,\n \tfor (i = 0; i < revs.pending.nr; i++) {\n \t\tstruct object_array_entry *e = revs.pending.objects + i;\n \t\tunsigned char sha1[20];\n-\t\tchar *ref;\n+\t\tconst char *ref;\n+\t\tint flag;\n \n \t\tif (e->item->flags & UNINTERESTING)\n \t\t\tcontinue;\n-\t\tif (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)\n+\t\tref = resolve_ref(e->name, sha1, 1, &flag);\n+\t\tif (!ref)\n \t\t\tcontinue;\n+\t\tif (flag & REF_ISSYMREF)\n+\t\t\tref = e->name;\n+\n \t\t/*\n \t\t * Make sure the refs we wrote out is correct; --max-count and\n \t\t * other limiting options could have prevented all the tips\n@@ -249,7 +255,6 @@ int create_bundle(struct bundle_header *header, const char *path,\n \t\tif (!(e->item->flags & SHOWN) && e->item->type == OBJ_COMMIT) {\n \t\t\twarning(\"ref '%s' is excluded by the rev-list options\",\n \t\t\t\te->name);\n-\t\t\tfree(ref);\n \t\t\tcontinue;\n \t\t}\n \t\t/*\n@@ -280,7 +285,6 @@ int create_bundle(struct bundle_header *header, const char *path,\n \t\t\t\tobj->flags |= SHOWN;\n \t\t\t\tadd_pending_object(&revs, obj, e->name);\n \t\t\t}\n-\t\t\tfree(ref);\n \t\t\tcontinue;\n \t\t}\n \n@@ -289,7 +293,6 @@ int create_bundle(struct bundle_header *header, const char *path,\n \t\twrite_or_die(bundle_fd, \" \", 1);\n \t\twrite_or_die(bundle_fd, ref, strlen(ref));\n \t\twrite_or_die(bundle_fd, \"\\n\", 1);\n-\t\tfree(ref);\n \t}\n \tif (!ref_count)\n \t\tdie (\"Refusing to create empty bundle.\");\n-- \n1.5.3.6.1977.g54d30\n"},{"id":"60543","messageId":"Pine.LNX.4.64.0711211658510.27959@racer.site","threadId":"10960","inReplyTo":"200711211752.40264.jnareb@gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T16:59:52Z","receivedAt":"2007-11-21T16:59:52Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Jakub Narebski wrote:\n\n> Johannes Schindelin wrote:\n> > On Wed, 21 Nov 2007, Jakub Narebski wrote:\n> >> Santi Bejar wrote:\n> >> \n> >>> 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n> >>> \n> >>> [remote \"bundle\"]\n> >>> \turl = /file/to/bundle\n> >>> \tfetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n> >>> \n> >>> $ git push bundle\n> >>> \n> >>> would create a bundle in /file/to/bundle with the same branches as a\n> >>> normal git push, but considering the remote branches as the local\n> >>> remotes/bundle/*\n> >> \n> >> And how you would differentiate between path meaning bundle, and path \n> >> meaning \"local\" protocol, i.e. git repository on the same filesystem? \n> > \n> > Maybe because the git repository is specified as an existing directory?  \n> > The bundle is specified as a (possibly non-existing) file...\n> \n> That has the disadvantage of pushing to bundle when you make an error\n> in the lastpart of path to existing repository.\n\nAs I wrote in another reply, I would not allow overwriting an existing \nfile.\n\n> After thinking about it a bit, I think it would be better to use \n> bundle:// pseudoprotocol for the URL including config (bundle://file, \n> bundle:///path/to/bundle) and --bundle option to git push for \n> commandline.\n\nI don't like that at all.\n\nSpecifying a non-existing file should be good enough.\n\nCiao,\nDscho\n"},{"id":"60548","messageId":"fi1ojd$pva$1@ger.gmane.org","threadId":"10960","inReplyTo":"8aa486160711210654p357ccd87i4809e0cda9471303@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-21T17:06:55Z","receivedAt":"2007-11-21T17:06:55Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"[Cc: Santi Béjar <sbejar@gmail.com>, git@vger.kernel.org]\n\nSanti Béjar wrote:\n\n> 1) git-clone does not accept a bundle file, even if git-fetch does.\n> I've made a patch to use git-fetch in git-clone for this.\n\n[...] \n> 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle\n\nWe would also need \"git ls-remote <bundle>\" and \"git fsck <bundle>\"\nto demote git-bundle to porcelain status :-)\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"60545","messageId":"Pine.LNX.4.64.0711211702440.27959@racer.site","threadId":"10960","inReplyTo":"1195662180.28318.19.camel@hinata.boston.redhat.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T17:07:51Z","receivedAt":"2007-11-21T17:07:51Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Kristian H?gsberg wrote:\n\n> On Wed, 2007-11-21 at 15:59 +0000, Johannes Schindelin wrote:\n> > Hi,\n> > \n> > On Wed, 21 Nov 2007, Santi B?jar wrote:\n> > \n> > > 1) git-clone does not accept a bundle file, even if git-fetch does. I've \n> > > made a patch to use git-fetch in git-clone for this.\n> > \n> > This, along with rewriting git-clone as a very thin wrapper over git-init, \n> > -remote and -fetch, is a really low hanging fruit.\n> > \n> > Or maybe go the full nine yards and build it in.  Should be a breeze now, \n> > given parse_options() and run_command().\n> \n> I started doing this, which is pretty stupid as I'm pressed to find time \n> to finish up builtin-commit.  Nevertheless, could you elaborate on the \n> plan here?  How would you rewrite it to just use remote and fetch?  I \n> just finished the boilerplate option parsing stuff (patch below) and \n> started reading the core of git-clone.sh, but if most of this can be \n> replaced I'd like to hear about it :)\n\nAfter handling the options like --reference, and except for special \nhandling of a local clone (not via file:// protocol), it should be as easy \nas\n\n\tgit remote add -f origin $url &&\n\tcase \"$no_checkout\" in\n\tt)\n\t\t;;\n\t*)\n\t\tgit checkout -f -b master remotes/origin/HEAD\n\t\t;;\n\tesac\n\n(Of course I'd use run_command() for this.)\n\nI would avoid at all costs to reimplement the different methods for the \ndifferent protocols.\n\nCiao,\nDscho\n"},{"id":"60546","messageId":"200711211811.34391.jnareb@gmail.com","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211658510.27959@racer.site","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-21T17:11:34Z","receivedAt":"2007-11-21T17:11:34Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Johannes Schindelin wrote:\n> On Wed, 21 Nov 2007, Jakub Narebski wrote:\n>> Johannes Schindelin wrote:\n>>> On Wed, 21 Nov 2007, Jakub Narebski wrote:\n>>>> Santi Bejar wrote:\n>>>> \n>>>>> 3) I can \"git fetch\" a bundle but I cannot \"git push\" a bundle, so if I have:\n>>>>> \n>>>>> [remote \"bundle\"]\n>>>>> \turl = /file/to/bundle\n>>>>> \tfetch = \"+refs/heads/*:refs/remotes/bundle/*\"\n>>>>> \n>>>>> $ git push bundle\n>>>>> \n>>>>> would create a bundle in /file/to/bundle with the same branches as a\n>>>>> normal git push, but considering the remote branches as the local\n>>>>> remotes/bundle/*\n>>>> \n>>>> And how you would differentiate between path meaning bundle, and path \n>>>> meaning \"local\" protocol, i.e. git repository on the same filesystem? \n>>> \n>>> Maybe because the git repository is specified as an existing directory?  \n>>> The bundle is specified as a (possibly non-existing) file...\n>> \n>> That has the disadvantage of pushing to bundle when you make an error\n>> in the lastpart of path to existing repository.\n> \n> As I wrote in another reply, I would not allow overwriting an existing \n> file.\n\n> Specifying a non-existing file should be good enough.\n\nWhat I meant here that if you do \"git push /some/path/to/rpeo.git\", with\nmistake in the last part of path to repository, you would end up with\na bundle, and you would have to really watch what happened to catch\nthe error.\n\nI'd rather use \"git push bundle:///some/path/to/bundle\" or \n\"git push --bundle bundlename\" to catch errors better.\n\nBesides it should be IMHO be possible to overwrite bundle if you are\ndoing fast-forward push...\n\n-- \nJakub Narebski\nPoland\n"},{"id":"60549","messageId":"Pine.LNX.4.64.0711211719330.27959@racer.site","threadId":"10960","inReplyTo":"200711211811.34391.jnareb@gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T17:26:36Z","receivedAt":"2007-11-21T17:26:36Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Jakub Narebski wrote:\n\n> Johannes Schindelin wrote:\n> > On Wed, 21 Nov 2007, Jakub Narebski wrote:\n> >\n> >> That has the disadvantage of pushing to bundle when you make an error \n> >> in the lastpart of path to existing repository.\n> > \n> > As I wrote in another reply, I would not allow overwriting an existing \n> > file.\n> \n> > Specifying a non-existing file should be good enough.\n> \n> What I meant here that if you do \"git push /some/path/to/rpeo.git\", with \n> mistake in the last part of path to repository, you would end up with a \n> bundle, and you would have to really watch what happened to catch the \n> error.\n\nI use tab completion all the time, so this would not happen to me.  IMHO \nthat is a lesser issue than to introduce a \"protocol\".\n\n> I'd rather use \"git push bundle:///some/path/to/bundle\" or \"git push \n> --bundle bundlename\" to catch errors better.\n> \n> Besides it should be IMHO be possible to overwrite bundle if you are \n> doing fast-forward push...\n\nNot as far as I can see.  A push there would see what the bundle has \nalready, and put them into the new bundle as _prerequisites_.  So the \nbundle would lose information.\n\nBTW this was my gripe (that I decided not to make public earlier) with \nSanti's proposal to begin with: a push would not have any way to specify \nwhat the other side has already.  So I think \"git push <bundle>\" is the \nwrong way of creating a bundle.\n\nExcept if we add some cunning strategy not to overwrite, ever, but to \ncreate <bundle>.<n> with an incrementing <n>.  But that might be too much.\n\nCiao,\nDscho\n"},{"id":"60550","messageId":"Pine.LNX.4.64.0711211728120.27959@racer.site","threadId":"10960","inReplyTo":"fi1ojd$pva$1@ger.gmane.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-21T17:29:50Z","receivedAt":"2007-11-21T17:29:50Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Jakub Narebski wrote:\n\n> We would also need \"git ls-remote <bundle>\" and \"git fsck <bundle>\" to \n> demote git-bundle to porcelain status :-)\n\ngit ls-remote <bundle> worked, last time I checked (15 seconds ago).  But \ngit fsck?  Since when does something like \"git fsck \ngit://repo.or.cz/git.git\" work?\n\nBesides, \"git bundle verify <bundle>\" works quite well.\n\nCiao,\nDscho\n"},{"id":"60551","messageId":"200711211852.03887.jnareb@gmail.com","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211719330.27959@racer.site","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-21T17:52:03Z","receivedAt":"2007-11-21T17:52:03Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Wed, 21 Nov 2007, Johannes Schindelin wrote:\n> On Wed, 21 Nov 2007, Jakub Narebski wrote:\n>> Johannes Schindelin wrote:\n>>> On Wed, 21 Nov 2007, Jakub Narebski wrote:\n>>>\n>>>> That has the disadvantage of pushing to bundle when you make an error \n>>>> in the lastpart of path to existing repository.\n>>> \n>>> As I wrote in another reply, I would not allow overwriting an existing \n>>> file.\n>> \n>>> Specifying a non-existing file should be good enough.\n>> \n>> What I meant here that if you do \"git push /some/path/to/rpeo.git\", with \n>> mistake in the last part of path to repository, you would end up with a \n>> bundle, and you would have to really watch what happened to catch the \n>> error.\n> \n> I use tab completion all the time, so this would not happen to me.  IMHO \n> that is a lesser issue than to introduce a \"protocol\".\n\nWhen I copy'n'paste pathname I sometimes catch return / linefeed in\nthe middle, ending with incorect pathname (which would create bundle).\nTab completon is not always solution (tab completion can be slow,\nor nonexistent).\n\n[cut]\n\nBut I agree that because \"git create bundle\" needs refspecs _and revlist_,\nwhile \"git push\" gets only refspecs because it calculates revlist it would\nbe better to have to use \"git bundle create\" to create bundle.\n\nContrary to \"git clone <bundle>\" which should just work IMHO.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"60627","messageId":"8aa486160711220142w25e9c9b6vbafa34a287dde7eb@mail.gmail.com","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211719330.27959@racer.site","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-22T09:42:42Z","receivedAt":"2007-11-22T09:42:42Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Nov 21, 2007 6:26 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n> On Wed, 21 Nov 2007, Jakub Narebski wrote:\n>\n> > Johannes Schindelin wrote:\n> > > On Wed, 21 Nov 2007, Jakub Narebski wrote:\n> > >\n> > >> That has the disadvantage of pushing to bundle when you make an error\n> > >> in the lastpart of path to existing repository.\n> > >\n> > > As I wrote in another reply, I would not allow overwriting an existing\n> > > file.\n> >\n> > > Specifying a non-existing file should be good enough.\n> >\n> > What I meant here that if you do \"git push /some/path/to/rpeo.git\", with\n> > mistake in the last part of path to repository, you would end up with a\n> > bundle, and you would have to really watch what happened to catch the\n> > error.\n>\n> I use tab completion all the time, so this would not happen to me.  IMHO\n> that is a lesser issue than to introduce a \"protocol\".\n>\n> > I'd rather use \"git push bundle:///some/path/to/bundle\" or \"git push\n> > --bundle bundlename\" to catch errors better.\n\nI would vote for the later, and a way to configure this in the config.\n\n> >\n> > Besides it should be IMHO be possible to overwrite bundle if you are\n> > doing fast-forward push...\n>\n> Not as far as I can see.  A push there would see what the bundle has\n> already, and put them into the new bundle as _prerequisites_.  So the\n> bundle would lose information.\n\nI prefer not to overwrite an existing bundle.\n\n>\n> BTW this was my gripe (that I decided not to make public earlier) with\n> Santi's proposal to begin with: a push would not have any way to specify\n> what the other side has already.  So I think \"git push <bundle>\" is the\n> wrong way of creating a bundle.\n\nSorry but I do not understand this. I think this two lines could be equivalent:\n\ngit push --bundle bundle.bdl \"refs/heads/master:refs/remotes/bundle/master\"\ngit bundle create bundle.bdl refs/heads/master ^refs/remotes/bundle/master\n\n>\n> Except if we add some cunning strategy not to overwrite, ever, but to\n> create <bundle>.<n> with an incrementing <n>.  But that might be too much.\n\nThat make sense.\n\nSanti\n"},{"id":"60632","messageId":"7v4pfe7g4e.fsf@gitster.siamese.dyndns.org","threadId":"10960","inReplyTo":"8aa486160711220142w25e9c9b6vbafa34a287dde7eb@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-22T10:02:09Z","receivedAt":"2007-11-22T10:02:09Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Santi Béjar\" <sbejar@gmail.com> writes:\n\n> Sorry but I do not understand this. I think this two lines could be equivalent:\n>\n> git push --bundle bundle.bdl \"refs/heads/master:refs/remotes/bundle/master\"\n> git bundle create bundle.bdl refs/heads/master ^refs/remotes/bundle/master\n\nInteresting.\n\n\t$ git push $something ours:theirs\n\nhas defined semantics for any value of $something.\n\n * give $something objects it lacks, so that the object $ours\n   become complete in there;\n\n * set the ref in $theirs to point at the object $ours.\n\nSo \"git push bundle.bdl refspec\" should:\n\n * First read bundle.bdl, to find out what objects it gives to\n   the recipients;\n\n * Add missing objects to it to make it up to date wrt \"ours\",\n   iow, fetching from the updated bundle would now give \"ours\";\n\n * Record the object \"ours\" as \"theirs\" ref, iow, listing\n   the updated bundle would show \"theis\" ref pointing at that\n   object.\n\nIf bundle.bdl does not exist yet, it is like pushing into a\nfreshly initialized empty repository.\n"},{"id":"60675","messageId":"Pine.LNX.4.64.0711221201240.27959@racer.site","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211652470.27959@racer.site","subject":"Re: [PATCH] bundle create: keep symbolic refs' names instead of resolving them","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-22T12:03:14Z","receivedAt":"2007-11-22T12:03:14Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Nov 2007, Johannes Schindelin wrote:\n\n> \n> When creating a bundle, symbolic refs used to be resolved to the\n> non-symbolic refs they point to before being written to the list\n> of contained refs.  I.e. \"git bundle create a1.bundle HEAD master\"\n> would show something like\n> \n> 388afe7881b33102fada216dd07806728773c011        refs/heads/master\n> 388afe7881b33102fada216dd07806728773c011        refs/heads/master\n\nAaargh.\n\nMy patch broke \"git bundle create x master\".  I somehow believed that \nresolve_ref () would turn \"master\" into \"refs/heads/master\", which it does \nnot do.\n\nSo please ignore this patch.\n\nCiao,\nDscho\n"},{"id":"60679","messageId":"Pine.LNX.4.64.0711221224230.27959@racer.site","threadId":"10960","inReplyTo":"Pine.LNX.4.64.0711211652470.27959@racer.site","subject":"[REPLACEMENT PATCH] bundle create: keep symbolic refs' names instead of resolving them","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-22T12:24:59Z","receivedAt":"2007-11-22T12:24:59Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhen creating a bundle, symbolic refs used to be resolved to the\nnon-symbolic refs they point to before being written to the list\nof contained refs.  I.e. \"git bundle create a1.bundle HEAD master\"\nwould show something like\n\n388afe7881b33102fada216dd07806728773c011        refs/heads/master\n388afe7881b33102fada216dd07806728773c011        refs/heads/master\n\ninstead of\n\n388afe7881b33102fada216dd07806728773c011        HEAD\n388afe7881b33102fada216dd07806728773c011        refs/heads/master\n\nIntroduce a special handling so that the symbolic refs are listed\nwith the names passed on the command line.\n\nNoticed by Santi Béjar.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\t... and this patch actually does not break the test suite.\n\n bundle.c |    9 ++++++++-\n 1 files changed, 8 insertions(+), 1 deletions(-)\n\ndiff --git a/bundle.c b/bundle.c\nindex e4d60cd..9b9b916 100644\n--- a/bundle.c\n+++ b/bundle.c\n@@ -6,6 +6,7 @@\n #include \"revision.h\"\n #include \"list-objects.h\"\n #include \"run-command.h\"\n+#include \"refs.h\"\n \n static const char bundle_signature[] = \"# v2 git bundle\\n\";\n \n@@ -232,11 +233,17 @@ int create_bundle(struct bundle_header *header, const char *path,\n \t\tstruct object_array_entry *e = revs.pending.objects + i;\n \t\tunsigned char sha1[20];\n \t\tchar *ref;\n+\t\tconst char *display_ref;\n+\t\tint flag;\n \n \t\tif (e->item->flags & UNINTERESTING)\n \t\t\tcontinue;\n \t\tif (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)\n \t\t\tcontinue;\n+\t\tif (!resolve_ref(e->name, sha1, 1, &flag))\n+\t\t\tflag = 0;\n+\t\tdisplay_ref = (flag & REF_ISSYMREF) ? e->name : ref;\n+\n \t\t/*\n \t\t * Make sure the refs we wrote out is correct; --max-count and\n \t\t * other limiting options could have prevented all the tips\n@@ -287,7 +294,7 @@ int create_bundle(struct bundle_header *header, const char *path,\n \t\tref_count++;\n \t\twrite_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);\n \t\twrite_or_die(bundle_fd, \" \", 1);\n-\t\twrite_or_die(bundle_fd, ref, strlen(ref));\n+\t\twrite_or_die(bundle_fd, display_ref, strlen(display_ref));\n \t\twrite_or_die(bundle_fd, \"\\n\", 1);\n \t\tfree(ref);\n \t}\n-- \n1.5.3.6.1977.g54d30\n\n"},{"id":"60743","messageId":"200711231018.49322.jnareb@gmail.com","threadId":"10960","inReplyTo":"7v4pfe7g4e.fsf@gitster.siamese.dyndns.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-23T09:18:48Z","receivedAt":"2007-11-23T09:18:48Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Thu, 22 Nov 2007, Junio C Hamano :\n> \"Santi Béjar\" <sbejar@gmail.com> writes:\n> \n>> Sorry but I do not understand this. I think this two lines could be equivalent:\n>>\n>> git push --bundle bundle.bdl \"refs/heads/master:refs/remotes/bundle/master\"\n>> git bundle create bundle.bdl refs/heads/master ^refs/remotes/bundle/master\n> \n> Interesting.\n> \n> \t$ git push $something ours:theirs\n> \n> has defined semantics for any value of $something.\n> \n>  * give $something objects it lacks, so that the object $ours\n>    become complete in there;\n> \n>  * set the ref in $theirs to point at the object $ours.\n> \n> So \"git push bundle.bdl refspec\" should:\n> \n>  * First read bundle.bdl, to find out what objects it gives to\n>    the recipients;\n> \n>  * Add missing objects to it to make it up to date wrt \"ours\",\n>    iow, fetching from the updated bundle would now give \"ours\";\n> \n>  * Record the object \"ours\" as \"theirs\" ref, iow, listing\n>    the updated bundle would show \"theirs\" ref pointing at that\n>    object.\n> \n> If bundle.bdl does not exist yet, it is like pushing into a\n> freshly initialized empty repository.\n\nBut for that I think \"git bundle\" should learn new subcommand:\n\"git bundle update\", which would use refs existing in given\nbundle as prerequisites, and either update bundle (create anew\nor just concatenate next pack) or create incremental bundle.\n\nSomething similar to incremental mode or update command of\narchivers...\n\n-- \nJakub Narebski\nPoland\n"},{"id":"60745","messageId":"7vejehux3y.fsf@gitster.siamese.dyndns.org","threadId":"10960","inReplyTo":"200711231018.49322.jnareb@gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-23T09:31:13Z","receivedAt":"2007-11-23T09:31:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> On Thu, 22 Nov 2007, Junio C Hamano :\n>> \"Santi Béjar\" <sbejar@gmail.com> writes:\n>> \n>>> Sorry but I do not understand this. I think this two lines could be equivalent:\n>>>\n>>> git push --bundle bundle.bdl \"refs/heads/master:refs/remotes/bundle/master\"\n>>> git bundle create bundle.bdl refs/heads/master ^refs/remotes/bundle/master\n>> \n>> Interesting.\n>> \n>> \t$ git push $something ours:theirs\n>> \n>> has defined semantics for any value of $something.\n>> ...\n>> If bundle.bdl does not exist yet, it is like pushing into a\n>> freshly initialized empty repository.\n>\n> But for that I think \"git bundle\" should learn new subcommand:\n> \"git bundle update\", which would use refs existing in given\n> bundle as prerequisites, and either update bundle (create anew\n> or just concatenate next pack) or create incremental bundle.\n>\n> Something similar to incremental mode or update command of\n> archivers...\n\nI was disagreeing with Santi's \"'push --bundle' and 'bundle\ncreate' can be equivalent\".  They can't be, as \"push\" is always\n\"update\" and never \"create\".  So I do not quite get your \"But for\nthat I think\"; I think you are just agreeing with me.\n\nEven if we taught \"push\" to create (which I doubt would happen\ndue to its security and administrative implications), it would\nnot make the two any closer to being equivalent.  For them to\nbecome equivalent, we would need to have \"push\" unlearn how to\nupdate, which would never happen ;-).\n"},{"id":"60749","messageId":"200711231104.32605.jnareb@gmail.com","threadId":"10960","inReplyTo":"7vejehux3y.fsf@gitster.siamese.dyndns.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-23T10:04:32Z","receivedAt":"2007-11-23T10:04:32Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Fri, 23 Nov 2007, Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n>> On Thu, 22 Nov 2007, Junio C Hamano :\n>>> \"Santi Béjar\" <sbejar@gmail.com> writes:\n>>> \n>>>> Sorry but I do not understand this. I think this two lines could be equivalent:\n>>>>\n>>>> git push --bundle bundle.bdl \"refs/heads/master:refs/remotes/bundle/master\"\n>>>> git bundle create bundle.bdl refs/heads/master ^refs/remotes/bundle/master\n>>> \n>>> Interesting.\n>>> \n>>> \t$ git push $something ours:theirs\n>>> \n>>> has defined semantics for any value of $something.\n>>> ...\n>>> If bundle.bdl does not exist yet, it is like pushing into a\n>>> freshly initialized empty repository.\n>>\n>> But for that I think \"git bundle\" should learn new subcommand:\n>> \"git bundle update\", which would use refs existing in given\n>> bundle as prerequisites, and either update bundle (create anew\n>> or just concatenate next pack) or create incremental bundle.\n>>\n>> Something similar to incremental mode or update command of\n>> archivers...\n> \n> I was disagreeing with Santi's \"'push --bundle' and 'bundle\n> create' can be equivalent\".  They can't be, as \"push\" is always\n> \"update\" and never \"create\".  So I do not quite get your \"But for\n> that I think\"; I think you are just agreeing with me.\n\nBad choice of words on my part... and I didn't parse that you were\ndisagreeing as well as commenting. :-/\n\n> Even if we taught \"push\" to create (which I doubt would happen\n> due to its security and administrative implications), it would\n> not make the two any closer to being equivalent.  For them to\n> become equivalent, we would need to have \"push\" unlearn how to\n> update, which would never happen ;-).\n\nI also think that pushing to bundle might be not a good idea;\nbut I think that \"git clone <bundle>\" should just work.\n\nNevertheless I think that having \"git bundle update\" or \n\"git bundle create --reference=<old bundle>\" (or both) would be\na good thing, as it would free us from remembering or tagging when\nlast bundle was created.\n\n\nCould anyone who uses \"git bundle\" actively raise a voice?\n\n-- \nJakub Narebski\nPoland\n"},{"id":"60753","messageId":"8aa486160711230213q6038037epe2cbd0240db8b612@mail.gmail.com","threadId":"10960","inReplyTo":"7vejehux3y.fsf@gitster.siamese.dyndns.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-23T10:13:55Z","receivedAt":"2007-11-23T10:13:55Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Nov 23, 2007 10:31 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> I was disagreeing with Santi's \"'push --bundle' and 'bundle\n> create' can be equivalent\".  They can't be, as \"push\" is always\n> \"update\" and never \"create\".  So I do not quite get your \"But for\n> that I think\"; I think you are just agreeing with me.\n>\n> Even if we taught \"push\" to create (which I doubt would happen\n> due to its security and administrative implications), it would\n> not make the two any closer to being equivalent.  For them to\n> become equivalent, we would need to have \"push\" unlearn how to\n> update, which would never happen ;-).\n>\n\nOK. So git push will never understand bundles.\n\nMy motivation was to have a similar workflow with bundles as with\npushes, or at least as similar as possible. So another possible\nworkflow would be with a:\n\ngit bundle push [<bundle> [<refspec>]]\n\nthat creates a bundle\n\n# Have a project with different branches (master, next, pu)\n$ git bundle push bundle.bdl\n# would create a complete bundle.bdl with all the local branches (with HEAD)\n\n# You send it to the other person and he does:\n$ git clone bundle.bdl project\n$ cat .git/config\n...\n[remote \"origin\"]\n        url = /path/to/bundle.bdl\n        fetch = +refs/heads/*:refs/remotes/origin/*\n\n# He makes changes, commits and so on and then he wants to send to back a bundle\n$ git bundle push [<remote>]\n# This creates an incremental bundle with the local branches (with\nHEAD) as specified\n# by remote.<remote>.* (possibly with an implicit \"push\" line\n\"refs/heads/*:refs/heads/*\"\n# And considering the remotes/origin/* as the bases for the bundle\n\n# Then I got it and do a:\n$ git remote add bundle /path/to/bundle\n$ git fetch\n\n# Now maybe I just want to send him the master branch\n$ git bundle push origin master:master\n\n# If I want to send him a complete bundle\n$ git bundle push\n\nThe important part, for me, is to keep remote tracking branches to\nknow the bases for the next bundle. It does not matter if it is \"git\npush\", \"git bundle push\", \"git push --bundle\", \"git bundle update\",\n...\n\nSanti\n"},{"id":"60758","messageId":"Pine.LNX.4.64.0711231132120.27959@racer.site","threadId":"10960","inReplyTo":"8aa486160711230213q6038037epe2cbd0240db8b612@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-23T12:18:30Z","receivedAt":"2007-11-23T12:18:30Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 23 Nov 2007, Santi B?jar wrote:\n\n> My motivation was to have a similar workflow with bundles as with \n> pushes, or at least as similar as possible. So another possible workflow \n> would be with a:\n> \n> git bundle push [<bundle> [<refspec>]]\n> \n> that creates a bundle\n\nWhat about\n\n\tgit bundle create retort.bundle --all \\\n\t\t--not $(git ls-remote the-other.bundle | cut -c1-40)\n\nHmm?\n\nIf you need that quite often, it should not be hard at all for you to add \nan option to the \"create\" named \"--haves-from=<bundle>\".\n\nBut I'd rather script it.\n\nCiao,\nDscho\n"},{"id":"60765","messageId":"7vabp5uhke.fsf@gitster.siamese.dyndns.org","threadId":"10960","inReplyTo":"8aa486160711230213q6038037epe2cbd0240db8b612@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-23T15:06:57Z","receivedAt":"2007-11-23T15:06:57Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Santi Béjar\" <sbejar@gmail.com> writes:\n\n> OK. So git push will never understand bundles.\n\nWhy not?  Because you will not code it?\n\nI am not opposed to the notion of \"pushing to a bundle to\nupdate it.\"  I am just saying that \"pushing to create\" only for\nbundle and not regular repository is very inconsistent.\n"},{"id":"60766","messageId":"8aa486160711230734l30a3e907rac5aee11f3518e88@mail.gmail.com","threadId":"10960","inReplyTo":"7vabp5uhke.fsf@gitster.siamese.dyndns.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-23T15:34:27Z","receivedAt":"2007-11-23T15:34:27Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Nov 23, 2007 4:06 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> \"Santi Béjar\" <sbejar@gmail.com> writes:\n>\n> > OK. So git push will never understand bundles.\n>\n> Why not?\n\nSorry, I misunderstood you, because pushing to an existing\nbundle loses information, and that is also inconsistent with pushing\nto regular repositories.\n\n>  Because you will not code it?\n>\n> I am not opposed to the notion of \"pushing to a bundle to\n> update it.\"  I am just saying that \"pushing to create\" only for\n> bundle and not regular repository is very inconsistent.\n\nSanti\n"},{"id":"60767","messageId":"7v63ztuevk.fsf@gitster.siamese.dyndns.org","threadId":"10960","inReplyTo":"8aa486160711230734l30a3e907rac5aee11f3518e88@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-23T16:05:03Z","receivedAt":"2007-11-23T16:05:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Santi Béjar\" <sbejar@gmail.com> writes:\n\n>> > OK. So git push will never understand bundles.\n>>\n>> Why not?\n>\n> Sorry, I misunderstood you, because pushing to an existing\n> bundle loses information, and that is also inconsistent with pushing\n> to regular repositories.\n\nMaybe I am missing something from the discussion, but what\ninformation loss are you referring to?\n"},{"id":"60768","messageId":"8aa486160711230839o5db5fca1wc09a834ab3d4f053@mail.gmail.com","threadId":"10960","inReplyTo":"7v63ztuevk.fsf@gitster.siamese.dyndns.org","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Santi Béjar","fromEmail":"sbejar@gmail.com","sentAt":"2007-11-23T16:39:06Z","receivedAt":"2007-11-23T16:39:06Z","isPatch":false,"sender":{"key":"santi@agolina.net","avatar":null},"body":"On Nov 23, 2007 5:05 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> \"Santi Béjar\" <sbejar@gmail.com> writes:\n>\n> >> > OK. So git push will never understand bundles.\n> >>\n> >> Why not?\n> >\n> > Sorry, I misunderstood you, because pushing to an existing\n> > bundle loses information, and that is also inconsistent with pushing\n> > to regular repositories.\n>\n> Maybe I am missing something from the discussion, but what\n> information loss are you referring to?\n>\n\nBecause you create an incremental bundle, so all the objects in the\nold bundle will\nnot be in the new bundle. But it can be considered the natural\nbehavior of bundles.\n\nBut anyway, pushing to an existing bundle is not very convenient (at\nleas for me) because it forces you to keep the bundles. I think the\nmost convenient way would be to have remote tracking branching to\nrecord the bases for future bundles.\n\nFor now, I will do an script that behaves like the \"git bundle push\"\nthat I described and then I'll report the pro/cons that it has.\n\nThank you all for the discussion, it was very fruitful.\n\nSanti\n\nP.D.: Am I the only one doing a bundle-only transport mode? If not,\ncan you comment on the different suggestions that have been said.\nThanks a lot.\n"},{"id":"60771","messageId":"200711232009.41739.jnareb@gmail.com","threadId":"10960","inReplyTo":"8aa486160711230734l30a3e907rac5aee11f3518e88@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-23T19:09:41Z","receivedAt":"2007-11-23T19:09:41Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Fri, 23 Nov 2007, Santi Béjar wrote:\n> On Nov 23, 2007 4:06 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> \"Santi Béjar\" <sbejar@gmail.com> writes:\n>>\n>>> OK. So git push will never understand bundles.\n>>\n>> Why not?\n> \n> Sorry, I misunderstood you, because pushing to an existing\n> bundle loses information, and that is also inconsistent with pushing\n> to regular repositories.\n\nPushing to regular repositories _adds_ information (adds objects\nand advances refs). Junio proposed that \"git push <bundle>\" do the\nsame, which means getting refs from bundle, and adding objects\nto bundle creating new bundle, which contain all the old one has,\nand all what was created since then. What information would be lost?\n\nJohannes provided alternate solution which you can use even now,\nnamely how to create \"incremental\" bundle, which has all objects\nsince last bundle was created. But this does not play with the way\npush works with ordinary, regular repositories.\n\nP.S. Code speaks louder than words ;-)\n-- \nJakub Narebski\nPoland\n"},{"id":"60820","messageId":"7voddjqwu0.fsf@gitster.siamese.dyndns.org","threadId":"10960","inReplyTo":"8aa486160711230839o5db5fca1wc09a834ab3d4f053@mail.gmail.com","subject":"Re: Wishlist for a bundle-only transport mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-24T19:15:19Z","receivedAt":"2007-11-24T19:15:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Santi Béjar\" <sbejar@gmail.com> writes:\n\n> On Nov 23, 2007 5:05 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> ...\n>> Maybe I am missing something from the discussion, but what\n>> information loss are you referring to?\n>\n> Because you create an incremental bundle, so all the objects in the\n> old bundle will\n> not be in the new bundle. But it can be considered the natural\n> behavior of bundles.\n\nIt might be natural if you are thinking within the limit of \"git\nbundle create\", but it is not natural for \"git push\" at all.\n\nI think treating a bundle as if it is a bare repository with a\nfunny representation wouldn't be so wrong, at least from the\nuser interface point of view.  IOW, I think it is natural for\nthese:\n\n\t$ git push $remote $refspec\n        $ git fetch $remote $refspec\n\nto work as \"expected\" when $remote is actually a local file that\nis a bundle, and in fact, \"git fetch\" should already work that\nway.\n\nWhat's \"expected\" for a push?  You push from your repository the\nobjects needed to complete LHS of given $refspec into the\n$remote, and then update the refs in the $remote specified by\nthe $refspec.  There is no deletion of existing objects from the\n$remote.  That is what's expected for a push.\n\nSo if you want to implement \"pushing into a bundle\", the\nimplementation would be:\n\n  * Find the required objects in the existing bundle.  If the\n    bundle file does not exist, it might be natural to treat it\n    as if you are pushing into an empty but initialized regular\n    repository.  If we choose to do this, for a nonexistent\n    bundle file, the set of required objects is an empty set.\n\n  * Find the recorded heads in the existing bundle.  Add or\n    replace them with the RHS of $refspecs being pushed to come\n    up with the new set of heads for the updated bundle.  We\n    would want to perform the ordinary \"fast-forward\" safety and\n    reject a push as needed.\n\n  * If there are HEADs in the updated bundle that the pushing\n    repository does not have, fetch them (and their required\n    objects) first, as it is necessary for the next step.\n\n  * Run this pipeline in the pushing repository to generate a\n    packdata stream:\n\n    $ git rev-list --objects <heads in the updated bundle> \\\n    \t--not <required objects in the bundle> |\n      git pack-objects --stdout\n\n    This packdata stream will be the payload of the updated\n    bundle.\n\n  * The updated bundle will require the same set of objects as\n    the bundle before the update.\n\nThis is quite different from the way how the other \"transports\"\nare implemented internally to push into usual repositories, but\nthat is perfectly fine.  What the end user sees will be\nconsistent if you implement \"push into bundle\" that way and that\nis what matters.\n\n\tNote.  I am not saying that we _should_ allow pushing\n\tinto a bundle to update.  I am just saying that if we\n\twere to implement \"git push\" into a bundle, that should\n        behave as close as other push transports from the end\n\tuesr's point of view.\n\nIf you want different \"object losing\" semantics, \"git bundle\ncreate\" to create a new bundle is already there for you.  You\njust shouldn't overload that different semantics to \"git push\",\nbecause that would confuse users without much gain.\n"}]}