{"thread":{"id":"11299","subject":"[RFE/PATCH] git-fetch-rebase","startedAt":"2007-12-14T22:12:31Z","lastAt":"2007-12-15T00:37:05Z","messageCount":3,"participants":["José Fonseca","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"63214","messageId":"1197670351.21175.33.camel@localhost","threadId":"11299","inReplyTo":null,"subject":"[RFE/PATCH] git-fetch-rebase","fromName":"José Fonseca","fromEmail":"jrfonseca@tungstengraphics.com","sentAt":"2007-12-14T22:12:31Z","receivedAt":"2007-12-14T22:12:31Z","isPatch":true,"sender":{"key":"jrfonseca@tungstengraphics.com","avatar":null},"body":"Hi,\n\nFor those who use git as a better centralized SCM, it became a common\npractice to do git-fetch + git-rebase instead of just git-pull, so that\nthe history is linear, instead of being full of tiny merges. \n\nHowever, there is no git command for such common procedure (at least\nAFAIK). Attached is a variation of the git-pull porcelain (taken from\ngit version debian.1.5.3.7.1-dirty) that instead of doing git-fetch +\ngit-merge, it does git-fetch + git-rebase.\n\nI've been using this git-fetch-rebase script frequently, and it really\nboosts my productivity (I use it when updating from the main repository,\nand before pushing my changes to the main repository).\n\nI'd like see this script, or an equivalent command, included the git\ndistribution.\n\nCheers,\n\nJosé Fonseca\n\n\n#!/bin/sh\n#\n# Copyright (c) 2007 JosÃ© Fonseca\n# Copyright (c) 2005 Junio C Hamano\n#\n# Fetch a remote ref and rebase the current HEAD on top of it.\n\nUSAGE='[-s strategy]... [<fetch-options>] <repo> <head>'\nLONG_USAGE='Fetch a remote ref and rebase the current HEAD onto it.'\nSUBDIRECTORY_OK=Yes\n. git-sh-setup\nset_reflog_action \"fetch-rebase $*\"\nrequire_work_tree\ncd_to_toplevel\n\ntest -z \"$(git ls-files -u)\" ||\n\tdie \"You are in the middle of a conflicted merge.\"\n\nstrategy_args=\nwhile :\ndo\n\tcase \"$1\" in\n\t-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\\\n\t\t--strateg=*|--strategy=*|\\\n\t-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)\n\t\tcase \"$#,$1\" in\n\t\t*,*=*)\n\t\t\tstrategy=`expr \"z$1\" : 'z-[^=]*=\\(.*\\)'` ;;\n\t\t1,*)\n\t\t\tusage ;;\n\t\t*)\n\t\t\tstrategy=\"$2\"\n\t\t\tshift ;;\n\t\tesac\n\t\tstrategy_args=\"${strategy_args}-s $strategy \"\n\t\t;;\n\t-h|--h|--he|--hel|--help)\n\t\tusage\n\t\t;;\n\t*)\n\t\t# Pass thru anything that may be meant for fetch.\n\t\tbreak\n\t\t;;\n\tesac\n\tshift\ndone\n\norig_head=$(git rev-parse --verify HEAD 2>/dev/null)\ngit-fetch \"$@\" || exit 1\n\nmerge_head=$(sed -e '/\tnot-for-merge\t/d' \\\n\t-e 's/\t.*//' \"$GIT_DIR\"/FETCH_HEAD | \\\n\ttr '\\012' ' ')\n\ncase \"$merge_head\" in\n'')\n\tcurr_branch=$(git symbolic-ref -q HEAD)\n\tcase $? in\n\t  0) ;;\n\t  1) echo >&2 \"You are not currently on a branch; you must explicitly\"\n\t     echo >&2 \"specify which branch you wish to rebase onto:\"\n\t     echo >&2 \"  git fetch-rebase <remote> <branch>\"\n\t     exit 1;;\n\t  *) exit $?;;\n\tesac\n\tcurr_branch=${curr_branch#refs/heads/}\n\n\techo >&2 \"You asked me to rebase without telling me which branch you\"\n\techo >&2 \"want to rebase, and 'branch.${curr_branch}.merge' in\"\n\techo >&2 \"your configuration file does not tell me either.  Please\"\n\techo >&2 \"name which branch you want to rebase on the command line and\"\n\techo >&2 \"try again (e.g. 'git fetch-rebase <repository> <refspec>').\"\n\techo >&2 \"See git-pull(1) for details on the refspec.\"\n\techo >&2\n\techo >&2 \"If you often rebase to the same branch, you may want to\"\n\techo >&2 \"configure the following variables in your configuration\"\n\techo >&2 \"file:\"\n\techo >&2\n\techo >&2 \"    branch.${curr_branch}.remote = <nickname>\"\n\techo >&2 \"    branch.${curr_branch}.merge = <remote-ref>\"\n\techo >&2 \"    remote.<nickname>.url = <url>\"\n\techo >&2 \"    remote.<nickname>.fetch = <refspec>\"\n\techo >&2\n\techo >&2 \"See git-config(1) for details.\"\n\texit 1\n\t;;\n?*' '?*)\n\techo >&2 \"Cannot rebase onto multiple branches\"\n\texit 1\n\t;;\nesac\n\nif test -z \"$orig_head\"\nthen\n\techo >&2 \"Cannot rebase empty head\"\n\texit 1\nfi\n\nexec git-rebase $strategy_args $merge_head\n\n\n--- /usr/bin/git-pull\t2007-12-04 09:46:21.000000000 +0000\n+++ git-fetch-rebase\t2007-12-13 12:38:52.000000000 +0000\n@@ -1,34 +1,25 @@\n #!/bin/sh\n #\n+# Copyright (c) 2007 JosÃ© Fonseca\n # Copyright (c) 2005 Junio C Hamano\n #\n-# Fetch one or more remote refs and merge it/them into the current HEAD.\n+# Fetch a remote ref and rebase the current HEAD on top of it.\n \n-USAGE='[-n | --no-summary] [--no-commit] [-s strategy]... [<fetch-options>] <repo> <head>...'\n-LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'\n+USAGE='[-s strategy]... [<fetch-options>] <repo> <head>'\n+LONG_USAGE='Fetch a remote ref and rebase the current HEAD onto it.'\n SUBDIRECTORY_OK=Yes\n . git-sh-setup\n-set_reflog_action \"pull $*\"\n+set_reflog_action \"fetch-rebase $*\"\n require_work_tree\n cd_to_toplevel\n \n test -z \"$(git ls-files -u)\" ||\n \tdie \"You are in the middle of a conflicted merge.\"\n \n-strategy_args= no_summary= no_commit= squash=\n+strategy_args=\n while :\n do\n \tcase \"$1\" in\n-\t-n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\\\n-\t\t--no-summa|--no-summar|--no-summary)\n-\t\tno_summary=-n ;;\n-\t--summary)\n-\t\tno_summary=$1\n-\t\t;;\n-\t--no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)\n-\t\tno_commit=--no-commit ;;\n-\t--sq|--squ|--squa|--squas|--squash)\n-\t\tsquash=--squash ;;\n \t-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\\\n \t\t--strateg=*|--strategy=*|\\\n \t-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)\n@@ -55,30 +46,7 @@\n done\n \n orig_head=$(git rev-parse --verify HEAD 2>/dev/null)\n-git-fetch --update-head-ok \"$@\" || exit 1\n-\n-curr_head=$(git rev-parse --verify HEAD 2>/dev/null)\n-if test \"$curr_head\" != \"$orig_head\"\n-then\n-\t# The fetch involved updating the current branch.\n-\n-\t# The working tree and the index file is still based on the\n-\t# $orig_head commit, but we are merging into $curr_head.\n-\t# First update the working tree to match $curr_head.\n-\n-\techo >&2 \"Warning: fetch updated the current branch head.\"\n-\techo >&2 \"Warning: fast forwarding your working tree from\"\n-\techo >&2 \"Warning: commit $orig_head.\"\n-\tgit update-index --refresh 2>/dev/null\n-\tgit read-tree -u -m \"$orig_head\" \"$curr_head\" ||\n-\t\tdie 'Cannot fast-forward your working tree.\n-After making sure that you saved anything precious from\n-$ git diff '$orig_head'\n-output, run\n-$ git reset --hard\n-to recover.'\n-\n-fi\n+git-fetch \"$@\" || exit 1\n \n merge_head=$(sed -e '/\tnot-for-merge\t/d' \\\n \t-e 's/\t.*//' \"$GIT_DIR\"/FETCH_HEAD | \\\n@@ -90,21 +58,21 @@\n \tcase $? in\n \t  0) ;;\n \t  1) echo >&2 \"You are not currently on a branch; you must explicitly\"\n-\t     echo >&2 \"specify which branch you wish to merge:\"\n-\t     echo >&2 \"  git pull <remote> <branch>\"\n+\t     echo >&2 \"specify which branch you wish to rebase onto:\"\n+\t     echo >&2 \"  git fetch-rebase <remote> <branch>\"\n \t     exit 1;;\n \t  *) exit $?;;\n \tesac\n \tcurr_branch=${curr_branch#refs/heads/}\n \n-\techo >&2 \"You asked me to pull without telling me which branch you\"\n-\techo >&2 \"want to merge with, and 'branch.${curr_branch}.merge' in\"\n+\techo >&2 \"You asked me to rebase without telling me which branch you\"\n+\techo >&2 \"want to rebase, and 'branch.${curr_branch}.merge' in\"\n \techo >&2 \"your configuration file does not tell me either.  Please\"\n-\techo >&2 \"name which branch you want to merge on the command line and\"\n-\techo >&2 \"try again (e.g. 'git pull <repository> <refspec>').\"\n+\techo >&2 \"name which branch you want to rebase on the command line and\"\n+\techo >&2 \"try again (e.g. 'git fetch-rebase <repository> <refspec>').\"\n \techo >&2 \"See git-pull(1) for details on the refspec.\"\n \techo >&2\n-\techo >&2 \"If you often merge with the same branch, you may want to\"\n+\techo >&2 \"If you often rebase to the same branch, you may want to\"\n \techo >&2 \"configure the following variables in your configuration\"\n \techo >&2 \"file:\"\n \techo >&2\n@@ -117,21 +85,15 @@\n \texit 1\n \t;;\n ?*' '?*)\n-\tif test -z \"$orig_head\"\n-\tthen\n-\t\techo >&2 \"Cannot merge multiple branches into empty head\"\n-\t\texit 1\n-\tfi\n+\techo >&2 \"Cannot rebase onto multiple branches\"\n+\texit 1\n \t;;\n esac\n \n if test -z \"$orig_head\"\n then\n-\tgit update-ref -m \"initial pull\" HEAD $merge_head \"\" &&\n-\tgit read-tree --reset -u HEAD || exit 1\n-\texit\n+\techo >&2 \"Cannot rebase empty head\"\n+\texit 1\n fi\n \n-merge_name=$(git fmt-merge-msg <\"$GIT_DIR/FETCH_HEAD\") || exit\n-exec git-merge $no_summary $no_commit $squash $strategy_args \\\n-\t\"$merge_name\" HEAD $merge_head\n+exec git-rebase $strategy_args $merge_head\n"},{"id":"63222","messageId":"7vy7bwomza.fsf@gitster.siamese.dyndns.org","threadId":"11299","inReplyTo":"1197670351.21175.33.camel@localhost","subject":"Re: [RFE/PATCH] git-fetch-rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-14T23:50:01Z","receivedAt":"2007-12-14T23:50:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"José Fonseca <jrfonseca@tungstengraphics.com> writes:\n\n> For those who use git as a better centralized SCM, it became a common\n> practice to do git-fetch + git-rebase instead of just git-pull, so that\n> the history is linear, instead of being full of tiny merges. \n\n\"git pull --rebase\"?\n"},{"id":"63226","messageId":"1197679025.21175.40.camel@localhost","threadId":"11299","inReplyTo":"7vy7bwomza.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFE/PATCH] git-fetch-rebase","fromName":"José Fonseca","fromEmail":"jrfonseca@tungstengraphics.com","sentAt":"2007-12-15T00:37:05Z","receivedAt":"2007-12-15T00:37:05Z","isPatch":true,"sender":{"key":"jrfonseca@tungstengraphics.com","avatar":null},"body":"On Fri, 2007-12-14 at 15:50 -0800, Junio C Hamano wrote:\n> José Fonseca <jrfonseca@tungstengraphics.com> writes:\n> \n> > For those who use git as a better centralized SCM, it became a common\n> > practice to do git-fetch + git-rebase instead of just git-pull, so that\n> > the history is linear, instead of being full of tiny merges. \n> \n> \"git pull --rebase\"?\n\nI didn't find it before. It seems a very recent functionality. Anyway,\nI'm glad it exists now.\n\nCheers,\n\nJosé Fonseca\n"}]}