{"thread":{"id":"27612","subject":"[PATCH] Preserve ORIG_HEAD if already up-to-date with remote.","startedAt":"2011-06-13T07:35:24Z","lastAt":"2011-07-17T16:31:24Z","messageCount":4,"participants":["Kunal Gangakhedkar","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"169923","messageId":"1307950525-8011-1-git-send-email-kunal.gangakhedkar@gmail.com","threadId":"27612","inReplyTo":null,"subject":"[PATCH] Preserve ORIG_HEAD if already up-to-date with remote.","fromName":"Kunal Gangakhedkar","fromEmail":"kunal.gangakhedkar@gmail.com","sentAt":"2011-06-13T07:35:24Z","receivedAt":"2011-06-13T07:35:24Z","isPatch":true,"sender":{"key":"kunal.gangakhedkar@gmail.com","avatar":null},"body":"By default, the ORIG_HEAD ref is moved to point to HEAD during a merge.\nIf there are no changes (i.e. if the local is in sync with remote), it\nbecomes difficult to see the last set of changes as the range of commits\nis lost.\n\nThis is especially true when the pull is performed via a cronjob or a\nscript.\n\nFollowing this mail is a patch that tries to address the problem \nby not updating the ORIG_HEAD ref when it detects an empty merge\n(i.e. local is in sync with the remote).\nThat way, one can still do diffstat/log between ORIG_HEAD..HEAD.\n\nIt's still possible to revert to old behavior with:\no. --force-update-orig-head cmd line option\no. merge.forceupdateorighead config option\n\nPlease review the patch and let me know if:\na) it makes sense to have this functionality\nb) if the patch looks OK\n\nPlease let me know if there are any changes required.\nI'll write the test cases and send them in another mail later.\n\nThanks,\nKunal\n\nKunal Gangakhedkar (1):\n  merge: Preserve ORIG_HEAD if already up-to-date with remote.\n\n builtin/merge.c |   26 ++++++++++++++++++++++++--\n 1 files changed, 24 insertions(+), 2 deletions(-)\n\n-- \n1.7.6.rc1.2.g20c4a.dirty\n"},{"id":"169924","messageId":"1307950525-8011-2-git-send-email-kunal.gangakhedkar@gmail.com","threadId":"27612","inReplyTo":"1307950525-8011-1-git-send-email-kunal.gangakhedkar@gmail.com","subject":"[PATCH] merge: Preserve ORIG_HEAD if already up-to-date with remote.","fromName":"Kunal Gangakhedkar","fromEmail":"kunal.gangakhedkar@gmail.com","sentAt":"2011-06-13T07:35:25Z","receivedAt":"2011-06-13T07:35:25Z","isPatch":true,"sender":{"key":"kunal.gangakhedkar@gmail.com","avatar":null},"body":"Do not update ORIG_HEAD ref to current HEAD if the repo is already\nin-sync with the remote.\n\nOtherwise, it becomes difficult to keep track of last set of changes.\n\nWith this patch, it's possible to do a diffstat/log for last set of\nchanges even after a pull/merge that returns 'Already up-to-date'.\nThis is especially useful when the pull is performed via a cronjob/script.\n\nThe old behaviour can still be forced via:\no. --force-update-orig-head cmd line option\no. merge.forceupdateorighead config option\n\nSigned-off-by: Kunal Gangakhedkar <kunal.gangakhedkar@gmail.com>\n---\n builtin/merge.c |   26 ++++++++++++++++++++++++--\n 1 files changed, 24 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 325891e..6ac26f0 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -63,6 +63,7 @@ static int allow_rerere_auto;\n static int abort_current_merge;\n static int show_progress = -1;\n static int default_to_upstream;\n+static int force_update_orig_head = 0;\n \n static struct strategy all_strategy[] = {\n \t{ \"recursive\",  DEFAULT_TWOHEAD | NO_TRIVIAL },\n@@ -206,6 +207,8 @@ static struct option builtin_merge_options[] = {\n \tOPT_BOOLEAN(0, \"abort\", &abort_current_merge,\n \t\t\"abort the current in-progress merge\"),\n \tOPT_SET_INT(0, \"progress\", &show_progress, \"force progress reporting\", 1),\n+\tOPT_BOOLEAN(0, \"force-update-orig-head\", &force_update_orig_head,\n+\t\t\t\"force-update ORIG_HEAD even if in sync with remote\"),\n \tOPT_END()\n };\n \n@@ -563,7 +566,11 @@ static int git_merge_config(const char *k, const char *v, void *cb)\n \t} else if (!strcmp(k, \"merge.defaulttoupstream\")) {\n \t\tdefault_to_upstream = git_config_bool(k, v);\n \t\treturn 0;\n+\t} else if (!strcmp(k, \"merge.forceupdateorighead\")) {\n+\t\tforce_update_orig_head = git_config_bool(k, v);\n+\t\treturn 0;\n \t}\n+\n \treturn git_diff_ui_config(k, v, cb);\n }\n \n@@ -1017,6 +1024,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \tstruct commit_list *common = NULL;\n \tconst char *best_strategy = NULL, *wt_strategy = NULL;\n \tstruct commit_list **remotes = &remoteheads;\n+\tint orig_head_updated = 0;\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_merge_usage, builtin_merge_options);\n@@ -1212,8 +1220,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tfree(list);\n \t}\n \n-\tupdate_ref(\"updating ORIG_HEAD\", \"ORIG_HEAD\", head, NULL, 0,\n-\t\tDIE_ON_ERR);\n+\tif (force_update_orig_head) {\n+\t\tupdate_ref(\"updating ORIG_HEAD\", \"ORIG_HEAD\", head, NULL, 0,\n+\t\t\tDIE_ON_ERR);\n+\t\torig_head_updated = 1;\n+\t}\n \n \tif (!common)\n \t\t; /* No common ancestors found. We need a real merge. */\n@@ -1254,6 +1265,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \n \t\tfinish(o->sha1, msg.buf);\n \t\tdrop_save();\n+\t\tif (!orig_head_updated) {\n+\t\t\tupdate_ref(\"updating ORIG_HEAD\", \"ORIG_HEAD\", head, NULL, 0,\n+\t\t\t\tDIE_ON_ERR);\n+\t\t\torig_head_updated = 1;\n+\t\t}\n \t\treturn 0;\n \t} else if (!remoteheads->next && common->next)\n \t\t;\n@@ -1306,6 +1322,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t}\n \t}\n \n+\tif (!orig_head_updated) {\n+\t\tupdate_ref(\"updating ORIG_HEAD\", \"ORIG_HEAD\", head, NULL, 0,\n+\t\t\tDIE_ON_ERR);\n+\t\torig_head_updated = 1;\n+\t}\n+\n \tif (fast_forward_only)\n \t\tdie(_(\"Not possible to fast-forward, aborting.\"));\n \n-- \n1.7.6.rc1.2.g20c4a.dirty\n"},{"id":"170035","messageId":"7vy614j99n.fsf@alter.siamese.dyndns.org","threadId":"27612","inReplyTo":"1307950525-8011-2-git-send-email-kunal.gangakhedkar@gmail.com","subject":"Re: [PATCH] merge: Preserve ORIG_HEAD if already up-to-date with remote.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-06-14T23:14:28Z","receivedAt":"2011-06-14T23:14:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kunal Gangakhedkar <kunal.gangakhedkar@gmail.com> writes:\n\n> Do not update ORIG_HEAD ref to current HEAD if the repo is already\n> in-sync with the remote.\n>\n> Otherwise, it becomes difficult to keep track of last set of changes.\n>\n> With this patch, it's possible to do a diffstat/log for last set of\n> changes even after a pull/merge that returns 'Already up-to-date'.\n\nI am not sure what you mean.  If you are behind remote A and remote B is\nbehind remote A, i.e.\n\n\tYou -- (fast forwards) --> B -- (fast forwards) --> A\n\nthen you should be able to expect these:\n\n\t: point zero\n\t$ git pull A\n        $ git diff/log ORIG_HEAD.. ;# shows how your tree and history\n        \t\t\t    # are updated wrt point zero above\n\t: point one\n\t$ git pull B\n        $ git diff/log ORIG_HEAD.. ;# shows how your tree and history\n        \t\t\t    # are updated wrt point one above\n\nIf your patch is to stop recording ORIG_HEAD for the second \"git pull\"\nabove, I fail to see how that could be a good change.\n\nIf you want to drive \"pull\" from a script (e.g. cron) and want to have\nprecise control of what happens depending on how HEAD is updated, your\nscript has enough freedom and flexibility to do so before running \"pull\",\nI think.  E.g.\n\n\t. $(git --exec-path)/git-sh-setup\n\n\tCURRENT=$(git rev-parse HEAD^0) || die \"Eh? No Head?\"\n        git pull || die \"pull fails\"\n        UPDATED=$(git rev-parse HEAD^0)\n        if test \"$CURRENT\" = \"$UPDATED\"\n        then\n\t\texit 0; # nothing happened\n\tfi\n\tgit shortlog --no-merges $CURRENT..$UPDATED\n        git diff --stat --summary $CURRENT..$UPDATED\n"},{"id":"171507","messageId":"201107172201.25242.kunal.gangakhedkar@gmail.com","threadId":"27612","inReplyTo":"7vy614j99n.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] merge: Preserve ORIG_HEAD if already up-to-date with remote.","fromName":"Kunal Gangakhedkar","fromEmail":"kunal.gangakhedkar@gmail.com","sentAt":"2011-07-17T16:31:24Z","receivedAt":"2011-07-17T16:31:24Z","isPatch":true,"sender":{"key":"kunal.gangakhedkar@gmail.com","avatar":null},"body":"On Wednesday 15 Jun 2011 4:44:28 am Junio C Hamano wrote:\n> Kunal Gangakhedkar <kunal.gangakhedkar@gmail.com> writes:\n> > Do not update ORIG_HEAD ref to current HEAD if the repo is already\n> > in-sync with the remote.\n> > \n> > Otherwise, it becomes difficult to keep track of last set of changes.\n> > \n> > With this patch, it's possible to do a diffstat/log for last set of\n> > changes even after a pull/merge that returns 'Already up-to-date'.\n> \n> I am not sure what you mean.  If you are behind remote A and remote B is\n> behind remote A, i.e.\n> \n> \tYou -- (fast forwards) --> B -- (fast forwards) --> A\n> \n> then you should be able to expect these:\n> \t: point zero\n> \n> \t$ git pull A\n>         $ git diff/log ORIG_HEAD.. ;# shows how your tree and history\n>         \t\t\t    # are updated wrt point zero above\n> \n> \t: point one\n> \n> \t$ git pull B\n>         $ git diff/log ORIG_HEAD.. ;# shows how your tree and history\n>         \t\t\t    # are updated wrt point one above\n> \n> If your patch is to stop recording ORIG_HEAD for the second \"git pull\"\n> above, I fail to see how that could be a good change.\n> \n> If you want to drive \"pull\" from a script (e.g. cron) and want to have\n> precise control of what happens depending on how HEAD is updated, your\n> script has enough freedom and flexibility to do so before running \"pull\",\n> I think.  E.g.\n> \n> \t. $(git --exec-path)/git-sh-setup\n> \n> \tCURRENT=$(git rev-parse HEAD^0) || die \"Eh? No Head?\"\n>         git pull || die \"pull fails\"\n>         UPDATED=$(git rev-parse HEAD^0)\n>         if test \"$CURRENT\" = \"$UPDATED\"\n>         then\n> \t\texit 0; # nothing happened\n> \tfi\n> \tgit shortlog --no-merges $CURRENT..$UPDATED\n>         git diff --stat --summary $CURRENT..$UPDATED\n\nSorry, got caught up in butt-load of work..\n\nWell, that's not what I meant.\nThe default diffstat at the end of merge/ff/pull already gives the required \ninfo.\n\nThe problem comes when the remote _does not_ have updates since last pull.\nWith a 'git pull' next time around (i.e. with no updates in the remote), \nORIG_HEAD is moved to the current HEAD and the range of commits in the last \nchangeset are lost. That is, I can no longer figure out the contents of the \nlast changeset.\n\nTo give an example, let's track the following sequence:\n\n\t$ git clone git://url/of/super-awesome/project.git  \t(0)\n\t\t.... hack hack hack in remote ....\n\t\t.... remote is fast-forwarded ...\n\t$ git pull\t\t\t\t\t\t\t\t\t(1)\n\t\t... you got the changes ....\n\t\t.... hack hack hack in remote ....\n\t\t.... remote is fast-forwarded ...\n\t$ git pull\t\t\t\t\t\t\t\t\t(2)\n\t\t... you got the changes ....\n\t\t... now, everybody is on vacation, so, no updates in remote ...\n\t$ git pull\t\t\t\t\t\t\t\t\t(3)\n\t\t... you get 'Already up-to-date.' message ...\n\t\t... everybody is still on vacation, so, no updates in remote  ...\n\t$ git pull\t\t\t\t\t\t\t\t\t(4) \n\t\t... you get 'Already up-to-date.' message ...\n\nIn the current situation, at the end of (3) above, ORIG_HEAD is moved to the \nthen HEAD. So, after (3), if I try to do \n\tgit diff/log ORIG_HEAD..\nI'd get an empty changeset - i.e. I've lost the *last updated* changeset \ninformation.\n\nWhat my patch does is keep ORIG_HEAD at its current state in (3) - so that \nchangeset info is still available after (3) until there is an update in \ntracked branch of remote. At which point, ORIG_HEAD will be forwarded again\nto the then HEAD and HEAD will point to the newly merged HEAD to reflect the \nchanges from remote.\n\nThis way, the *latest* changeset is always available for inspection whether \nthere's been an update in remote or not. I can safely do \n\tgit diff/log ORIG_HEAD..\nafter (4) as well and I'd still get the required information.\n\nI've included config/cmdline options in the patch to force-update ORIG_HEAD so \nthat current behavior is retained.\n\nPlease let me know if it makes sense.\n\nI've written a simple test script for the functionality, but I'm not sure how \nto name it. Currently, in my working copy, it's called \n\tt5555-merge-preserve-orig-head.sh\nIf that's fine, I'll send it in another patch for review. Otherwise, please \nsuggest a good name for it.\n\nThanks,\nKunal\n"}]}