{"thread":{"id":"43146","subject":"Re: Stupid Git question","startedAt":"2006-11-21T21:41:32Z","lastAt":"2006-11-24T08:31:05Z","messageCount":7,"participants":["Carl Worth","Junio C Hamano","Sean Kelley","Jakub Narebski"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"297659","messageId":"89b129c60611211341j71079633g53b0ec1d2e3193a5@mail.gmail.com","threadId":"43146","inReplyTo":"89b129c60611211331r3bb286b6re3c2c8f65ec3896f@mail.gmail.com","subject":"Stupid Git question","fromName":"Sean Kelley","fromEmail":"sean.v.kelley@gmail.com","sentAt":"2006-11-21T21:41:32Z","receivedAt":"2006-11-21T21:41:32Z","isPatch":false,"sender":{"key":"sean.v.kelley@gmail.com","avatar":null},"body":"Hi,\n\nI have a stupid git question.  We are doing embedded development using\ngit for our kernel mods.\n\ngit clone git+ssh://git.example.com/git/kernel/mh.git kernel\n\ngit checkout -b fm-modulator\n\nedit/add/commit\n\ngit checkout origin\n\ngit pull . fm-modulator\n\ngit push origin\n\nEverything up-to-date  <<< It pushes nothing\n\nMy problem is that I don't understand why when I tell git to push the\nchanges to our repository it says everything is up-to-date.  It\nclearly hasn't pushed it yet to our server.\n\nMy git layout is like this:\n\nA single repository representing our Monahans kernel \"mh.git\"  hosted\non a remote server accessed by git+ssh.\n\nFour developers work on the kernel and drivers for the target platform.\n\nAny suggestions much appreciated.  My prior experience is with\nStarTeam and more recently Subversion.\n\nThanks,\n\nSean\n\n-- \nSean Kelley\n\n-- \n"},{"id":"298683","messageId":"ejvs65$vo8$1@sea.gmane.org","threadId":"43146","inReplyTo":"89b129c60611211341j71079633g53b0ec1d2e3193a5@mail.gmail.com","subject":"Re: Stupid Git question","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-21T21:49:21Z","receivedAt":"2006-11-21T21:49:21Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Sean Kelley wrote:\n\n> git checkout origin\n\nIt should be \"git checkout master\". You shouldn't do work on tracking\nbranches like origin branch.\n\n> git pull . fm-modulator\n> \n> git push origin\n\nHere origin means origin remote (repository). Check out what you have in\nremotes/origin, or in [remote \"origin\"] section in git config.\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"296353","messageId":"89b129c60611220628l59e305b8h4d2196f7cf6498d4@mail.gmail.com","threadId":"43146","inReplyTo":"ejvs65$vo8$1@sea.gmane.org","subject":"Re: Stupid Git question","fromName":"Sean Kelley","fromEmail":"sean.v.kelley@gmail.com","sentAt":"2006-11-22T14:28:58Z","receivedAt":"2006-11-22T14:28:58Z","isPatch":false,"sender":{"key":"sean.v.kelley@gmail.com","avatar":null},"body":"On 11/21/06, Jakub Narebski <jnareb@gmail.com> wrote:\n> Sean Kelley wrote:\n>\n> > git checkout origin\n>\n> It should be \"git checkout master\". You shouldn't do work on tracking\n> branches like origin branch.\n>\n> > git pull . fm-modulator\n> >\n> > git push origin\n>\n> Here origin means origin remote (repository). Check out what you have in\n> remotes/origin, or in [remote \"origin\"] section in git config.\n\n\nThanks!  One more question.  It appears that the problem that I am\nhaving is that people are comitting to origin and should be committing\nto master.  Perhaps the names can be confusing.  One suggestion made\nis that we give a branch on the remote server a more meaningful name.\n\nIf on my remote server I have:\n\n  /data/git/kernel/mh.git\n\nHow do I add a branch to the remote repository that is visible to all\nteam members.  It seems like the git checkout -b commands just create\nlocal topic branches.\n\nSo I would have something like:\n\ngit clone git+ssh://git.example.com/data/git/kernel/mh.git kernel\ncd kernel\ngit checkout Project\ngit checkout -b fm-modulator\nedit/add/commit changes...\n\ngit checkout Project\ngit pull . fm-modulator\ngit push origin Project\n\nSo how do I create this Project branch on the remote repository such\nthat it is visible to all?  Do I log onto the remove server and do it\nmanually?  If so, how is that done?\n\nThanks!\n\nSean\n\n> --\n> Jakub Narebski\n> Warsaw, Poland\n> ShadeHawk on #git\n>\n>\n> -\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n>\n\n\n-- \n"},{"id":"293916","messageId":"871wnvxwg4.wl%cworth@cworth.org","threadId":"43146","inReplyTo":"89b129c60611220628l59e305b8h4d2196f7cf6498d4@mail.gmail.com","subject":"Re: Stupid Git question","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-11-22T16:44:43Z","receivedAt":"2006-11-22T16:44:43Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Wed, 22 Nov 2006 08:28:58 -0600, \"Sean Kelley\" wrote:\n> How do I add a branch to the remote repository that is visible to all\n> team members.  It seems like the git checkout -b commands just create\n> local topic branches.\n\nJust push the branch out to the remote repository. You even gave the\ncommand sequence to do that:\n\n> git checkout Project\n> git pull . fm-modulator\n> git push origin Project\n\n-Carl\n"},{"id":"297720","messageId":"89b129c60611221328l333d22c6o3668aef2706f92c7@mail.gmail.com","threadId":"43146","inReplyTo":"871wnvxwg4.wl%cworth@cworth.org","subject":"Re: Stupid Git question","fromName":"Sean Kelley","fromEmail":"sean.v.kelley@gmail.com","sentAt":"2006-11-22T21:28:42Z","receivedAt":"2006-11-22T21:28:42Z","isPatch":false,"sender":{"key":"sean.v.kelley@gmail.com","avatar":null},"body":"Hi,\n\nOn 11/22/06, Carl Worth <cworth@cworth.org> wrote:\n> On Wed, 22 Nov 2006 08:28:58 -0600, \"Sean Kelley\" wrote:\n> > How do I add a branch to the remote repository that is visible to all\n> > team members.  It seems like the git checkout -b commands just create\n> > local topic branches.\n>\n> Just push the branch out to the remote repository. You even gave the\n> command sequence to do that:\n>\n> > git checkout Project\n> > git pull . fm-modulator\n> > git push origin Project\n>\n\nOne other question - how do you rename a branch on the remote\nrepository once you have created it?\n\nThanks,\n\nSean\n\n> -Carl\n>\n>\n>\n\n\n-- \n"},{"id":"295038","messageId":"7vac2jp0g6.fsf@assigned-by-dhcp.cox.net","threadId":"43146","inReplyTo":"89b129c60611221328l333d22c6o3668aef2706f92c7@mail.gmail.com","subject":"Re: Stupid Git question","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-22T22:43:05Z","receivedAt":"2006-11-22T22:43:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Sean Kelley\" <sean.v.kelley@gmail.com> writes:\n\n> One other question - how do you rename a branch on the remote\n> repository once you have created it?\n\nRight now, there is no way to remove a ref, so even \"create new\nand then remove\" would not work.  You need a way to ssh-in to\nthe machine and run \"branch -d\" there.\n\nYou would need an access to run git tools on the remote site\nfor:\n\n - repository creation and deletion\n - ref deletion\n - fsck, pruning and repacking\n - adding entries to objects/info/alternates\n - managing hook scripts\n\nwith the current set of tools, which pretty much means an\naccount with a full shell access over SSH.\n\nEarlier in another thread, Linus said that it is justifiable to\ntreat repository creation as a special event and outside of\ngit.  For one thing you need to have the account on the site and\narrange access permissions and authentication before you can\ncreate a repository, so it is an understandable position to\ntake, and for people with full SSH access it is a minor nuisance\nthat they have to first go there to perform the above operations\ninstead of running \"git-do-things-at-remote host:path\" locally.\n\nHowever, for sites that want to restrict the access via\ngit-shell, after a repository owner secured such an account and\naccess rights, not being able to allow the user to do some of\nthe above things himself is a burden on site administrators.\nThis _could_ be improved by allowing some common operations via\ngit-shell.\n\nEven under git-shell, the process'es user and group\ncredentials are the primary means to control the access\nrights.  So in that sense, letting the user to say things\nlike the following might make sense:\n\n   $ REPO=repo.example.com:/pub/scm/git/project.git\n   $ git remote-admin $REPO create-repository\n   $ git remote-admin $REPO delete-repository\n   $ git remote-admin $REPO repack\n   $ git remote-admin $REPO fsck-objects\n   $ git remote-admin $REPO count-objects\n\nAnd for the sake of both simplicity (which would lead to\nsecurity) and to allow the site administrator to make policy\ndecision, I think we do not have to (and we shouldn't) make the\nabove commands to take any flags.  The command's availability\nand what parameters to be passed to underlying commands such as\ngit-repack are determined by the site administrator.  For\nexample, an administrator may give a restricted account to a\nuser _and_ set up one repository for him but may not want to\ngive him rights to create another repository nor delete that\ninitial repository given to him, in which case create-repository\nand delete-repository actions would be disabled.\n\nI have a feeling that the users should not be given full control\nover 'hook' scripts, but I am not sure.  A site administator\nmight want to forbid too expensive hooks from running, even the\nprocess spawned by the user would work only in directories that\nthe user has access to.  If we give the users a full control,\nthen:\n\n   $ git remote-admin $REPO get-hook $hookname >old-contents\n   $ git remote-admin $REPO put-hook $hookname <new-contents\n   $ git remote-admin $REPO remove-hook $hookname\n\nwould be the set of commands we could use (I am assuming\nput-hook installs the hook in \"enabled\" state, and get-hook\nwould give a failure for nonexistent or disabled hooks).\n\nThe most straightforward extension of the above for ref deletion\nis to say:\n\n   $ git remote-admin $REPO delete-refs refs/heads/foo refs/tags/v1.0\n\nand that would be the simplest way to implement it if we were to\ngo with \"git remote-admin\".  However, I think people would find\nit more natural if manipulation of refs were part of \"git push\".\n\n\"git push $REPO $src:$dst\" means \"take what I have in $src in my\nlocal repository, and update the $REPO's $dst ref with that\".\nSo as a natural extension of that, we could make:\n\n   $ git push $REPO '':$dst\n\nto mean \"store nothingness in $dst\" and make that a way to\nexpress the desire to remove $dst ref.\n\n"},{"id":"295994","messageId":"7v3b89dz5i.fsf@assigned-by-dhcp.cox.net","threadId":"43146","inReplyTo":"7vac2jp0g6.fsf@assigned-by-dhcp.cox.net","subject":"Re: Stupid Git question","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-24T08:31:05Z","receivedAt":"2006-11-24T08:31:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <junkio@cox.net> writes:\n\n>...\n> The most straightforward extension of the above for ref deletion\n> is to say:\n>\n>    $ git remote-admin $REPO delete-refs refs/heads/foo refs/tags/v1.0\n>\n> and that would be the simplest way to implement it if we were to\n> go with \"git remote-admin\".  However, I think people would find\n> it more natural if manipulation of refs were part of \"git push\".\n>\n> \"git push $REPO $src:$dst\" means \"take what I have in $src in my\n> local repository, and update the $REPO's $dst ref with that\".\n> So as a natural extension of that, we could make:\n>\n>    $ git push $REPO '':$dst\n>\n> to mean \"store nothingness in $dst\" and make that a way to\n> express the desire to remove $dst ref.\n\nAnd here is an attempt to do so.  Only lightly tested...\n\n\tWhenever I say \"only lightly tested\", I am hoping that\n\tinterested people on the list to test it and possibly\n\tenhance it with follow-up patches.  Or at least respond\n\twith \"Hey, that sucks\" or \"Ok, it seems to work for your\n\ttest case but here is a breakage\".\n\n-- >8 --\n[PATCH] Allow git push to delete remote ref.\n\nThis allows you to say\n\n\tgit send-pack $URL :refs/heads/$branch\n\nto delete the named remote branch.  The refspec $src:$dst means\nreplace the destination ref with the object known as $src on the\nlocal side, so this is a natural extension to make an empty $src\nmean \"No object\" to delete the target.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n connect.c            |   11 ++++++++++-\n receive-pack.c       |   45 ++++++++++++++++++++++++++++++++++-----------\n send-pack.c          |   41 ++++++++++++++++++++++++++++++-----------\n t/t5400-send-pack.sh |   10 ++++++++++\n 4 files changed, 84 insertions(+), 23 deletions(-)\n\ndiff --git a/connect.c b/connect.c\nindex b9666cc..f7edba8 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -144,6 +144,7 @@ struct refspec {\n  * +A:B means overwrite remote B with local A.\n  * +A is a shorthand for +A:A.\n  * A is a shorthand for A:A.\n+ * :B means delete remote B.\n  */\n static struct refspec *parse_ref_spec(int nr_refspec, char **refspec)\n {\n@@ -240,6 +241,13 @@ static struct ref *try_explicit_object_n\n \tunsigned char sha1[20];\n \tstruct ref *ref;\n \tint len;\n+\n+\tif (!*name) {\n+\t\tref = xcalloc(1, sizeof(*ref) + 20);\n+\t\tstrcpy(ref->name, \"(delete)\");\n+\t\thashclr(ref->new_sha1);\n+\t\treturn ref;\n+\t}\n \tif (get_sha1(name, sha1))\n \t\treturn NULL;\n \tlen = strlen(name) + 1;\n@@ -262,7 +270,8 @@ static int match_explicit_refs(struct re\n \t\t\tbreak;\n \t\tcase 0:\n \t\t\t/* The source could be in the get_sha1() format\n-\t\t\t * not a reference name.\n+\t\t\t * not a reference name.  :refs/other is a\n+\t\t\t * way to delete 'other' ref at the remote end.\n \t\t\t */\n \t\t\tmatched_src = try_explicit_object_name(rs[i].src);\n \t\t\tif (matched_src)\ndiff --git a/receive-pack.c b/receive-pack.c\nindex d56898c..1a141dc 100644\n--- a/receive-pack.c\n+++ b/receive-pack.c\n@@ -14,7 +14,7 @@ static int deny_non_fast_forwards = 0;\n static int unpack_limit = 5000;\n static int report_status;\n \n-static char capabilities[] = \"report-status\";\n+static char capabilities[] = \" report-status delete-refs \";\n static int capabilities_sent;\n \n static int receive_pack_config(const char *var, const char *value)\n@@ -113,12 +113,14 @@ static int update(struct command *cmd)\n \n \tstrcpy(new_hex, sha1_to_hex(new_sha1));\n \tstrcpy(old_hex, sha1_to_hex(old_sha1));\n-\tif (!has_sha1_file(new_sha1)) {\n+\n+\tif (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {\n \t\tcmd->error_string = \"bad pack\";\n \t\treturn error(\"unpack should have generated %s, \"\n \t\t\t     \"but I can't find it!\", new_hex);\n \t}\n-\tif (deny_non_fast_forwards && !is_null_sha1(old_sha1)) {\n+\tif (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&\n+\t    !is_null_sha1(old_sha1)) {\n \t\tstruct commit *old_commit, *new_commit;\n \t\tstruct commit_list *bases, *ent;\n \n@@ -138,14 +140,22 @@ static int update(struct command *cmd)\n \t\treturn error(\"hook declined to update %s\", name);\n \t}\n \n-\tlock = lock_any_ref_for_update(name, old_sha1);\n-\tif (!lock) {\n-\t\tcmd->error_string = \"failed to lock\";\n-\t\treturn error(\"failed to lock %s\", name);\n+\tif (is_null_sha1(new_sha1)) {\n+\t\tif (delete_ref(name, old_sha1)) {\n+\t\t\tcmd->error_string = \"failed to delete\";\n+\t\t\treturn error(\"failed to delete %s\", name);\n+\t\t}\n+\t\tfprintf(stderr, \"%s: %s -> deleted\\n\", name, old_hex);\n+\t}\n+\telse {\n+\t\tlock = lock_any_ref_for_update(name, old_sha1);\n+\t\tif (!lock) {\n+\t\t\tcmd->error_string = \"failed to lock\";\n+\t\t\treturn error(\"failed to lock %s\", name);\n+\t\t}\n+\t\twrite_ref_sha1(lock, new_sha1, \"push\");\n+\t\tfprintf(stderr, \"%s: %s -> %s\\n\", name, old_hex, new_hex);\n \t}\n-\twrite_ref_sha1(lock, new_sha1, \"push\");\n-\n-\tfprintf(stderr, \"%s: %s -> %s\\n\", name, old_hex, new_hex);\n \treturn 0;\n }\n \n@@ -375,6 +385,16 @@ static void report(const char *unpack_st\n \tpacket_flush(1);\n }\n \n+static int delete_only(struct command *cmd)\n+{\n+\twhile (cmd) {\n+\t\tif (!is_null_sha1(cmd->new_sha1))\n+\t\t\treturn 0;\n+\t\tcmd = cmd->next;\n+\t}\n+\treturn 1;\n+}\n+\n int main(int argc, char **argv)\n {\n \tint i;\n@@ -408,7 +428,10 @@ int main(int argc, char **argv)\n \n \tread_head_info();\n \tif (commands) {\n-\t\tconst char *unpack_status = unpack();\n+\t\tconst char *unpack_status = NULL;\n+\n+\t\tif (!delete_only(commands))\n+\t\t\tunpack_status = unpack();\n \t\tif (!unpack_status)\n \t\t\texecute_commands();\n \t\tif (pack_lockfile)\ndiff --git a/send-pack.c b/send-pack.c\nindex 4476666..328dbbc 100644\n--- a/send-pack.c\n+++ b/send-pack.c\n@@ -271,6 +271,7 @@ static int send_pack(int in, int out, in\n \tint new_refs;\n \tint ret = 0;\n \tint ask_for_status_report = 0;\n+\tint allow_deleting_refs = 0;\n \tint expect_status_report = 0;\n \n \t/* No funny business with the matcher */\n@@ -280,6 +281,8 @@ static int send_pack(int in, int out, in\n \t/* Does the other end support the reporting? */\n \tif (server_supports(\"report-status\"))\n \t\task_for_status_report = 1;\n+\tif (server_supports(\"delete-refs\"))\n+\t\tallow_deleting_refs = 1;\n \n \t/* match them up */\n \tif (!remote_tail)\n@@ -299,9 +302,19 @@ static int send_pack(int in, int out, in\n \tnew_refs = 0;\n \tfor (ref = remote_refs; ref; ref = ref->next) {\n \t\tchar old_hex[60], *new_hex;\n+\t\tint delete_ref;\n+\n \t\tif (!ref->peer_ref)\n \t\t\tcontinue;\n-\t\tif (!hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {\n+\n+\t\tdelete_ref = is_null_sha1(ref->peer_ref->new_sha1);\n+\t\tif (delete_ref && !allow_deleting_refs) {\n+\t\t\terror(\"remote does not support deleting refs\");\n+\t\t\tret = -2;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!delete_ref &&\n+\t\t    !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {\n \t\t\tif (verbose)\n \t\t\t\tfprintf(stderr, \"'%s': up-to-date\\n\", ref->name);\n \t\t\tcontinue;\n@@ -321,9 +334,13 @@ static int send_pack(int in, int out, in\n \t\t *\n \t\t * (3) if both new and old are commit-ish, and new is a\n \t\t *     descendant of old, it is OK.\n+\t\t *\n+\t\t * (4) regardless of all of the above, removing :B is\n+\t\t *     always allowed.\n \t\t */\n \n \t\tif (!force_update &&\n+\t\t    !delete_ref &&\n \t\t    !is_zero_sha1(ref->old_sha1) &&\n \t\t    !ref->force) {\n \t\t\tif (!has_sha1_file(ref->old_sha1) ||\n@@ -347,12 +364,8 @@ static int send_pack(int in, int out, in\n \t\t\t}\n \t\t}\n \t\thashcpy(ref->new_sha1, ref->peer_ref->new_sha1);\n-\t\tif (is_zero_sha1(ref->new_sha1)) {\n-\t\t\terror(\"cannot happen anymore\");\n-\t\t\tret = -3;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tnew_refs++;\n+\t\tif (!delete_ref)\n+\t\t\tnew_refs++;\n \t\tstrcpy(old_hex, sha1_to_hex(ref->old_sha1));\n \t\tnew_hex = sha1_to_hex(ref->new_sha1);\n \n@@ -366,10 +379,16 @@ static int send_pack(int in, int out, in\n \t\telse\n \t\t\tpacket_write(out, \"%s %s %s\",\n \t\t\t\t     old_hex, new_hex, ref->name);\n-\t\tfprintf(stderr, \"updating '%s'\", ref->name);\n-\t\tif (strcmp(ref->name, ref->peer_ref->name))\n-\t\t\tfprintf(stderr, \" using '%s'\", ref->peer_ref->name);\n-\t\tfprintf(stderr, \"\\n  from %s\\n  to   %s\\n\", old_hex, new_hex);\n+\t\tif (delete_ref)\n+\t\t\tfprintf(stderr, \"deleting '%s'\\n\", ref->name);\n+\t\telse {\n+\t\t\tfprintf(stderr, \"updating '%s'\", ref->name);\n+\t\t\tif (strcmp(ref->name, ref->peer_ref->name))\n+\t\t\t\tfprintf(stderr, \" using '%s'\",\n+\t\t\t\t\tref->peer_ref->name);\n+\t\t\tfprintf(stderr, \"\\n  from %s\\n  to   %s\\n\",\n+\t\t\t\told_hex, new_hex);\n+\t\t}\n \t}\n \n \tpacket_flush(out);\ndiff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh\nindex 8afb899..28744b3 100755\n--- a/t/t5400-send-pack.sh\n+++ b/t/t5400-send-pack.sh\n@@ -64,6 +64,16 @@ test_expect_success \\\n \tcmp victim/.git/refs/heads/master .git/refs/heads/master\n '\n \n+test_expect_success \\\n+        'push can be used to delete a ref' '\n+\tcd victim &&\n+\tgit branch extra master &&\n+\tcd .. &&\n+\ttest -f victim/.git/refs/heads/extra &&\n+\tgit-send-pack ./victim/.git/ :extra master &&\n+\t! test -f victim/.git/refs/heads/extra\n+'\n+\n unset GIT_CONFIG GIT_CONFIG_LOCAL\n HOME=`pwd`/no-such-directory\n export HOME ;# this way we force the victim/.git/config to be used.\n-- \n1.4.4.1.g77614\n\n"}]}