{"thread":{"id":"1973","subject":"Pull from one branch to another?","startedAt":"2005-09-29T06:07:57Z","lastAt":"2005-09-29T17:52:10Z","messageCount":7,"participants":["Jeff Garzik","Junio C Hamano","Alan Chandler","Matthias Urlichs","Tony Luck"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"9459","messageId":"433B84BD.8030003@pobox.com","threadId":"1973","inReplyTo":null,"subject":"Pull from one branch to another?","fromName":"Jeff Garzik","fromEmail":"jgarzik@pobox.com","sentAt":"2005-09-29T06:07:57Z","receivedAt":"2005-09-29T06:07:57Z","isPatch":false,"sender":{"key":"jgarzik@pobox.com","avatar":null},"body":"\nI currently use the attached script to merge the contents of one branch \ninto another branch, in my kernel trees:\n\n\t$ cd /repo/netdev-2.6\n\t$ git checkout -f sky2\n\t$ ... merge patches ...\n\t$ git checkout -f upstream\n\t$ ... merge more patches ...\n\t$ git checkout -f ALL\n\t$ git-pull-branch upstream\n\t$ git-pull-branch sky2\n\nEnd result:  'ALL' branch contains everything in 'sky2' and 'upstream' \nbranches.  I use the above for creating an all-inclusive branch that \nusers can test, and that Andrew Morton can pull into his -mm kernel tree.\n\nRight now, my git-pull-branch script (attached) simply calls \ngit-resolve-script, which nicely skips the fetch step and any \ncomplications related to that.\n\nMy question:  is this the best/right way to pull one branch into \nanother?  It's been working for me, for months, but...\n\n\tJeff\n\n\n\n\n\n#!/bin/sh\n\ngit-resolve-script HEAD $1 \"`pwd` branch '$1'\"\n\n"},{"id":"9462","messageId":"7vbr2cmle2.fsf@assigned-by-dhcp.cox.net","threadId":"1973","inReplyTo":"433B84BD.8030003@pobox.com","subject":"Re: Pull from one branch to another?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-29T06:35:33Z","receivedAt":"2005-09-29T06:35:33Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff Garzik <jgarzik@pobox.com> writes:\n\n> My question:  is this the best/right way to pull one branch into \n> another?  It's been working for me, for months, but...\n\nYes, that is how 'resolve' is designed to work.\n\nYou could instead use standard 'git pull' from the local\nrepository.  Here is what I usually do in git.git repository:\n\n    $ git checkout foo\n    $ ... work in foo \"topic\" branch\n    $ git checkout bar\n    $ ... work in bar \"topic\" branch\n    $ git checkout pu\n    $ git pull . foo bar\n\nEnd result: foo and bar branches are pulled from the local\nrepository and merged into pu branch, as an Octopus.\n\nOf course, I could instead:\n\n    $ git checkout pu\n    $ git pull . foo\n    $ git pull . bar\n\nto pull 'foo' and then 'bar' in sequence, which is easier if\nthese topic branches touch overlapping area, because Octopus\ndoes not allow manual resolving.  On the other hand if I know\nfoo and bar are independent work, there is no point recording\nthe order of merges (merging foo first and then bar does not\nhave any significance) and I tend to let Octopus to happen.\n"},{"id":"9463","messageId":"200509290754.30017.alan@chandlerfamily.org.uk","threadId":"1973","inReplyTo":"7vbr2cmle2.fsf@assigned-by-dhcp.cox.net","subject":"Use of the -f flag on checkout","fromName":"Alan Chandler","fromEmail":"alan@chandlerfamily.org.uk","sentAt":"2005-09-29T06:54:29Z","receivedAt":"2005-09-29T06:54:29Z","isPatch":false,"sender":{"key":"alan@chandlerfamily.org.uk","avatar":"https://gravatar.com/avatar/1862247e5ea8eac114c842f9dc3a5db6253754e24ef7171757cf97eedce48b8c?d=mp&s=160"},"body":"On Thursday 29 Sep 2005 07:35, Junio C Hamano wrote:\n> Jeff Garzik <jgarzik@pobox.com> writes:\n> > My question:  is this the best/right way to pull one branch into\n> > another?  It's been working for me, for months, but...\n>\n> Yes, that is how 'resolve' is designed to work.\n>\n> You could instead use standard 'git pull' from the local\n> repository.  Here is what I usually do in git.git repository:\n>\n>     $ git checkout foo\n>     $ ... work in foo \"topic\" branch\n>     $ git checkout bar\n>     $ ... work in bar \"topic\" branch\n>     $ git checkout pu\n\nI notice that Jeff is using the -f flag on checkout whereas you don't.\n\nWhat is the risk in not using it (ie what are the cases when you should use \nit)?\n\n-- \nAlan Chandler\nhttp://www.chandlerfamily.org.uk\n"},{"id":"9464","messageId":"7vvf0kl5de.fsf@assigned-by-dhcp.cox.net","threadId":"1973","inReplyTo":"433B84BD.8030003@pobox.com","subject":"Re: Pull from one branch to another?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-29T07:06:53Z","receivedAt":"2005-09-29T07:06:53Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff Garzik <jgarzik@pobox.com> writes:\n\n> ... It's been working for me, for months, but...\n\n ... will stop working as of Oct 1st? ;-)\n\n> git-resolve-script HEAD $1 \"`pwd` branch '$1'\"\n\nIt is planned that we will stop installing *-script\ncompatibility symbolic links starting as of 0.99.8.\n"},{"id":"9465","messageId":"pan.2005.09.29.07.09.51.516956@smurf.noris.de","threadId":"1973","inReplyTo":"200509290754.30017.alan@chandlerfamily.org.uk","subject":"Re: Use of the -f flag on checkout","fromName":"Matthias Urlichs","fromEmail":"smurf@smurf.noris.de","sentAt":"2005-09-29T07:09:52Z","receivedAt":"2005-09-29T07:09:52Z","isPatch":false,"sender":{"key":"matthias@urlichs.de","avatar":"https://gravatar.com/avatar/2708905af227313eba6f2b2ae0f7d0259b5ac5d71baef58fe5a13c699ce0bbf0?d=mp&s=160"},"body":"Hi, Alan Chandler wrote:\n\n> What is the risk in not using it (ie what are the cases when you should\n> use it)?\n\nThe risk of using it is that you kill your local changes, even if you want\nto keep them. They're *gone*.\n\nThe risk of not using it is that you check local changes into a branch\nwhere they don't belong.\n\n=> IMHO, \"checkout -f\" should be avoided in scripts. If you want to be\nsafe, check that you don't have local changes or additional files *before*\ndoing the work.\n\n-- \nMatthias Urlichs   |   {M:U} IT Design @ m-u-it.de   |  smurf@smurf.noris.de\nDisclaimer: The quote was selected randomly. Really. | http://smurf.noris.de\n - -\nTo me, home is not rooms and places. It is the people I want to be with.\n\t\t-- FJ van Wingerde\n"},{"id":"9472","messageId":"7vpsqsgsbt.fsf@assigned-by-dhcp.cox.net","threadId":"1973","inReplyTo":"200509290754.30017.alan@chandlerfamily.org.uk","subject":"Re: Use of the -f flag on checkout","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-09-29T09:02:14Z","receivedAt":"2005-09-29T09:02:14Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alan Chandler <alan@chandlerfamily.org.uk> writes:\n\n> I notice that Jeff is using the -f flag on checkout whereas you don't.\n>\n> What is the risk in not using it (ie what are the cases when you should use \n> it)?\n\n'git checkout' without '-f' means \"I know my index file is\nderived from my current HEAD commit.  I may have recorded\nchanges since the HEAD commit in index and also in the working\ntree.  I now want to switch to the named branch head commit but\nI'd like to take those local changes with me.\"\n\nMy examples worked in topic branches and after finishing work in\neach branch (meaning, making commits to record changes to each\nbranch I was working on), switched to another branch.  After\nmaking a commit, the index file exactly matches the current HEAD\n(i.e. \"git diff HEAD\" would report empty) and the working tree\nexactly matches the index file (i.e. \"git diff\" would report\nempty too), so there is no local changes to carry around.\n\nNote that this is not always possible.  If the local\nmodifications you have contradict with what the switched-to\nbranch has, 'git checkout' would complain and refuse to check\nthings out.  But if you know your index file and the working\ntree is in sync with the HEAD commit, 'git checkout' is the\npreferred way to switch branches.  It is somewhat more efficient,\ntoo.\n\nOn the other hand, what 'git checkout -f' is telling git is that\n\"I do not want you to trust what the index file records or what\nthe current HEAD is.  I just want to have my index matched to\nthe named branch head commit, and have those blobs recorded in\nthat commit checked out in the working tree\".  It is designed to\nwork even when you do not have a clue about the relationship\nbetween what your index records, what your working tree files\nare and what your current HEAD commit has, and can be used as\nthe last resort after a failed merge really messed up your\nworking tree and you would rather start the merge from scratch.\nSwitching to the current branch ('git checkout -f HEAD') makes\nsense in that situation, while 'git checkout HEAD' never does.\n\nHere is a short demonstration (my \"ls\" is aliased to \"ls -aF\").\n\n        $ git show-branch\n        * [master] Initial - have frotz\n         ! [nitfol] Add nitfol\n          ! [rezrov] Add rezrov\n        ---\n          + [rezrov] Add rezrov\n         +  [nitfol] Add nitfol\n        +++ [master] Initial - have frotz\n        $ ls\n        ./  ../  .git/\tfrotz\n\nThe 'master' branch has one file, 'frotz'.  Two branches are\nderived from it, 'rezrov' and 'nitfol', each adds one file with\nthe same name as the branch name, without touching 'frotz'.  We\nare on the 'master' branch.\n\n        $ git checkout nitfol\n        $ git ls-files\n        frotz\n        nitfol\n        $ ls\n        ./  ../  .git/\tfrotz  nitfol\n\nWe use 'git checkout' without '-f'.  It checked out 'nitfol' and\nkept 'frotz'.\n\n        $ git checkout -f rezrov\n        $ git ls-files\n        frotz\n        rezrov\n        $ ls\n        ./  ../  .git/\tfrotz  nitfol  rezrov\n\nThis time, we tried 'git checkout' with '-f'.  It checked out\n'rezrov' and kept 'frotz', but failed to remove 'nitfol',\nbecause we told it to ignore the fact that we came from 'nitfol'\nbranch.  If it were allowed to use that information, it would\nhave noticed that the original branch had 'nitfol' recorded but\nthe branch we are switching to did not have it, and would have\nremoved it from the working tree.  Also notice that the index\nfile matches the 'rezrov' commit -- it does not know about\n'nitfol' file anymore.\n\n        $ rm -f nitfol\n        $ date >xyzzy\n        $ git add xyzzy\n\nNow, after removing the unwanted 'nitfol' file, let's introduce\nsome local changes.  Remember we are still on 'rezrov' branch.\n\n        $ git checkout nitfol\n        $ git ls-files\n        frotz\n        nitfol\n        xyzzy\n        $ ls\n        ./  ../  .git/\tfrotz  nitfol  xyzzy\n        $ git diff --name-status HEAD\n        A\txyzzy\n\nNow we tell 'git checkout' to switch to 'nitfol' branch, without\nlosing our local changes.  The file 'nitfol' is back (checked\nout), and 'rezrov' is gone (because this time it was allowed to\ntrust the current HEAD and noticed 'rezrov' was there in the\noriginal but not in the branch we are switching to).\n\nHowever, neither the working file nor the index matches the\n'nitfol' branch head -- it kept the local addition of new file\n'xyzzy' (i.e. your local changes were preserved).\n\nOne typical scenario I use 'git checkout' without '-f' is:\n\n    * on some branch, start working on something.\n    * realize that the change I am making belongs to a different\n      topic.\n    * 'git checkout' to that other topic branch, with my\n      changes.\n    * keep working and make commit on the other topic branch.\n    * come back (with 'git checkout') to the original branch.\n\nBut usually I am even less organized -- I'd usually end up\ndoing:\n\n    * on some branch, start working on something.\n    * realize that some the changes I am making belong to a\n      different topic, while other changes belong to the\n      curren branch.\n    * stash away \"git diff HEAD\" output.  revert parts that\n      are not relevant to the current topic branch.\n    * make commit on the current topic branch.\n    * 'git checkout' to that other topic branch.  Apply the\n      rest of the diff output.\n    * keep working and make commit on the other topic branch.\n\nPersonally I don't remember using 'git checkout -f' myself.\nWhen I really want to sync my index file and the working tree to\nthe current branch head, I tend to do 'git reset --hard'\ninstead.  Unlike 'git checkout -f HEAD', this removes the files\nI added to the working tree and the index since my current HEAD\ncommit.  One downside is that 'git reset --hard' *is* a very\nexpensive operation.\n"},{"id":"9487","messageId":"12c511ca0509291052108fa0a7@mail.gmail.com","threadId":"1973","inReplyTo":"433B84BD.8030003@pobox.com","subject":"Re: Pull from one branch to another?","fromName":"Tony Luck","fromEmail":"tony.luck@gmail.com","sentAt":"2005-09-29T17:52:10Z","receivedAt":"2005-09-29T17:52:10Z","isPatch":false,"sender":{"key":"tony.luck@gmail.com","avatar":null},"body":"On 9/28/05, Jeff Garzik <jgarzik@pobox.com> wrote:\n\n>         $ git checkout -f sky2\n...\n>         $ git checkout -f upstream\n...\n>         $ git checkout -f ALL\n\nThose \"-f\" arguments to git checkout shouldn't be needed, and may\neventually cause a problem.  The \"-f\" option doesn't quite work as\n\"forcibly\" as you might think it does because it ignores the index, and\nso doesn't do what you[1] expect with files that exist in the previously\nchecked out tree, and not in the new tree ... it won't delete them, so\nthere's a small risk that with the wrong git operation you may\naccidentally add them to the new branch.\n\nIn the sequence you described a simple \"git checkout\" should do the\nright thing ... and will be faster too.\n\n-Tony\n\n[1] well what *I* expected, and was part of a snafu I made earlier\n"}]}