{"thread":{"id":"23161","subject":"Picking up multiple cherries at one go.","startedAt":"2010-03-24T08:47:41Z","lastAt":"2010-03-24T11:52:22Z","messageCount":3,"participants":["Jozef Babjak","Alex Riesen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"137694","messageId":"ffef8f9a1003240147o777d058jfacd79aa86908925@mail.gmail.com","threadId":"23161","inReplyTo":null,"subject":"Picking up multiple cherries at one go.","fromName":"Jozef Babjak","fromEmail":"jozef.babjak@gmail.com","sentAt":"2010-03-24T08:47:41Z","receivedAt":"2010-03-24T08:47:41Z","isPatch":false,"sender":{"key":"jozef.babjak@gmail.com","avatar":null},"body":"Hello all!\n\nI'm a quite new git fellow, but I must to say that the git already\naffected my development work significantly. I found out that almost\nall imaginable tasks related to VCS are directly supported by git\nout-of-the-box and all tools are very pragmatic. Great!\n\nHowever, last days I needed to split a long multi-purpose branch into\nseveral topic branches. The branch was created as a result of 'general\ncleanup and refactoring', but at the end of day I realized that some\nwell-defined parts can be identified there and so I wanted to extract\nthem to dedicated branches. Thus, cherry-pick and rebase were my\nfriend for couple of days. Everything goes well, but there was a\nrepetitive task - cherry picking multiple commits. Sometimes the\nprocess failed, because cherry picking led to conflicts. To simplify\nthis task, I wrote the shell script attached at the end of this\nemail.The script named git_cherries.sh reads commit IDs from stdin and\ncherry-picks those commits to current branch. Everything is done on an\nauxilliary branch, so the process is transactional - it succeed\ncompletelly or it does not change anything. You can find more detailed\ninformation at the beginning of te script.\n\nPlease try the script and feel free to use it, if you consider it to\nbe useful. It would be nice to have something similar in git suite.\nAny feedback is appreciated.\n\nJozef Babjak\n\n\n---- git_cherries.sh ---\n\n#! /bin/sh\n\n##\n## This script cherry-picks more commits at one go. Commit IDs are read\n## from standard input and applied to the current branch. Everything is\n## done on auxilliary branch under the hood, so the change is done\n## completely or it is not done at all. This is useful when refactoring\n## a long multi-purpose branch into several separated branches.\n##\n## Usage [just an example, but you got the idea]:\n##\n##      git checkout master\n##      git checkout -b new_topic\n##      git log --pretty=oneline master..multi_topic_branch | \\\n##              tail -n 5 | cut -f 1 -d \" \" | tac | git_cherries.sh\n##\n## The commands above gets the last 5 commits from 'multi_topic_branch'\n## and applies them to newly created 'new_topic' branch. Please note\n## that tac(1) is used to reverse order of commits to applying them in\n## proper order.\n##\n## Any additional command line arguments are without change passed to\n## git-cherry-pick(1) command. This makes sense for -x, -r, -s and -n\n## options.\n##\n## Program needs to be invoked only from root of a GIT repository.\n##\n\nif [ ! -d \"./.git\" ] ; then\n        echo \"This is not a root directory of any GIT repository: '`pwd`'\"\n        exit 1\nfi\n\ncurrent_branch=`git branch | grep '*' | cut -f 2 -d \" \"`\n\ntmp_branch=\"${current_branch}_cherrypicking_${$}\"\n\n##\n## Auxilliary branch creation.\n##\ngit checkout --quiet -b \"${tmp_branch}\"\n\n##\n## Applying cherry picks.\n##\nwhile read commit ; do\n        git show --pretty=oneline \"${commit}\" | head -n 1\n        git cherry-pick \"${@}\" \"${commit}\" > /dev/null 2>&1 ||\ncherry_pick_failed=\"true\"\n        if [ ! -z \"${cherry_pick_failed}\" ] ; then\n                break\n        fi\ndone\n\n##\n## We are done with cherry picking now. If 'cherry_pick_failed' is\n## set something went wrong and we cannot merge auxilliary branch.\n##\nif [ ! -z \"${cherry_pick_failed}\" ] ; then\n        git reset --hard -q\nfi\n\ngit checkout --quiet \"${current_branch}\"\n\nif [ -z \"${cherry_pick_failed}\" ] ; then\n        git merge \"${tmp_branch}\"\nfi\n\n##\n## Success or not, delete auxilliary branch.\n##\ngit branch -D \"${tmp_branch}\" > /dev/null\n\nif [ -z \"${cherry_pick_failed}\" ] ; then\n        echo \"Done.\" 1>&2\n        exit 0\nelse\n        echo \"Failed: ${commit}\" 1>&2\n        exit 1\nfi\n"},{"id":"137695","messageId":"81b0412b1003240221o53196568r9c8f2e0b7a2f1fd7@mail.gmail.com","threadId":"23161","inReplyTo":"ffef8f9a1003240147o777d058jfacd79aa86908925@mail.gmail.com","subject":"Re: Picking up multiple cherries at one go.","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2010-03-24T09:21:29Z","receivedAt":"2010-03-24T09:21:29Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Wed, Mar 24, 2010 at 09:47, Jozef Babjak <jozef.babjak@gmail.com> wrote:\n> However, last days I needed to split a long multi-purpose branch into\n> several topic branches. The branch was created as a result of 'general\n> cleanup and refactoring', but at the end of day I realized that some\n> well-defined parts can be identified there and so I wanted to extract\n> them to dedicated branches. Thus, cherry-pick and rebase were my\n> friend for couple of days. Everything goes well, but there was a\n> repetitive task - cherry picking multiple commits. Sometimes the\n> process failed, because cherry picking led to conflicts. ...\n\nTry git rebase -i (interactive) next time. It does not exactly what your\nscript does, but ... You may like it.\n\n> To simplify this task, I wrote the shell script attached at the end of this\n> email.The script named git_cherries.sh reads commit IDs from stdin and\n> cherry-picks those commits to current branch. Everything is done on an\n> auxilliary branch, ...\n\nYou can commit without a branch (called \"detached HEAD\").\nTry \"git checkout HEAD^0\", for example.\nNo need to invent new branch names (and risk collisions).\n"},{"id":"137700","messageId":"81b0412b1003240452v57026439x7647535391e299fb@mail.gmail.com","threadId":"23161","inReplyTo":"ffef8f9a1003240236x34be6051ja8d013453d88d3a1@mail.gmail.com","subject":"Re: Picking up multiple cherries at one go.","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2010-03-24T11:52:22Z","receivedAt":"2010-03-24T11:52:22Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Please, don't strip gitml from cc. Your questions maybe interesting to\nsomeone else.\n\nOn Wed, Mar 24, 2010 at 10:36, Jozef Babjak <jozef.babjak@gmail.com> wrote:\n> Thanks for hint. I did not used interactive git commands ever; maybe I\n> should try.\n>\n>> Try git rebase -i (interactive) next time. It does not exactly what your\n>> script does, but ... You may like it.\n>\n>  ^-- Do you mean to make a copy of the multi_purpose_branch first and\n> then to rebase interactively that new base onto master or any other\n> ancestor branch and removing unwanted comits? The issue is that I\n> usually want to keep only small portion of commits in newly created\n> topic branch. It seems to be easier to mark somehow 5 commits I want\n> instead of 95 commits I do not want.\n\nYou'll be amazed how easy it is (and how nothing it costs) to make a copy\nof a branch: \"git branch tmp\". And you can rebase-interactive a portion\nof the branch you're on: \"git rebase -i HEAD~10\". This will consider last\n10 commits for cherry-picking. And even if you want to review all 100\ncommits, it maybe not that hard if you have a plain text file with subject\nlines of the commits (and their sha1). You always can start a history\nbrowser of your choice (gitk?) to help you with that.\nAt least that's how I do that since Johannes invented rebase-interactive.\n"}]}