2

I would like to create a new branch with a copy of one particular commit only (from master, i.e.). How do I do that?

The closest I got to that is something like:

git checkout --orphan NEWBRANCH
git rm -rf .
git commit "MESSAGE MESSAGE MESSAGE"
git cherry-pick -x <hash>

Basically, I would like the above without the "MESSAGE MESSAGE MESSAGE" commit.

I got an error after cherry-pick:

$ git cherry-pick -x 68cc6733a14ec571c0abb0d4e77f53d93446f009
error: could not apply 68cc673... asdvasdflmdamfvla
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
KcFnMi
  • 5,516
  • 10
  • 62
  • 136
  • The question's not clear. You want to make a new branch that starts with an empty repository and cherry-picks a single commit? Or you want to start a new branch at a particular commit (including all it's history)? Or something else? – mkasberg Sep 23 '16 at 13:40
  • In the new branch I would like only one commit, without history. – KcFnMi Sep 23 '16 at 13:42
  • 5
    possible duplicate of http://stackoverflow.com/questions/13969050/how-to-create-a-new-empty-branch-for-a-new-project#13969482 – GiftZwergrapper Sep 23 '16 at 13:43

1 Answers1

2
git checkout --orphan NEWBRANCH <commitid>
git commit -a

git checkout --orphan <new_branch> [<start_point>]

Create a new orphan branch, named <new_branch>, started from <start_point> and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.

The index and the working tree are adjusted as if you had previously run "git checkout <start_point>". This allows you to start a new history that records a set of paths similar to <start_point> by easily running "git commit -a" to make the root commit.


EDIT

The following script will do the job in a single shot (note that in order to eliminate possible causes for failure, it will need to clean the working tree from untracked files, but it will ask for permission of doing so):

copy_as_root_commit

#!/bin/sh

myname="$(basename "$0")"

if [ $# -ne 2 ]
then
    echo 1>&2 "Usage: $myname <commitid> <new_branch>"
    exit 1
fi


commitid=$(git rev-parse "$1")
new_branch="$2"

set -e
untracked_stuff="$(git clean -dxf -n)"
if [ "$untracked_stuff" ]
then
    echo "$myname needs to clean the working tree before proceeding:"
    printf "%s\n" "$untracked_stuff"
    while read -p "Remove above files? (y/n) " answer
    do
        case "$answer" in
            [yY]) break ;;
            [nN]) exit 1 ;;
        esac
    done
fi

git clean -dxf                                               \
&& git checkout --orphan "$new_branch" "$commitid"           \
&& git commit -m "Initial commit (a copy of $commitid)"      \
&& echo "Successfully created new root branch '$new_branch'" \
|| echo "Failed to create new root branch '$new_branch'"

Usage:

copy_as_root_commit <commitid> <new_branch>

Examples:

copy_as_root_commit master~4 NEW_ROOT

copy_as_root_commit ce04aa6 NEWBRANCH
Leon
  • 31,443
  • 4
  • 72
  • 97
  • 1
    This way leaves no traces of which commit it comes from. The alternative using `cherry-pick -x` solve this issue. – KcFnMi Sep 23 '16 at 15:32
  • 1
    @KcFnMi With `git cherry-pick -x` the only connection to the source commit is through the commit message. Nothing prevents you from putting that information in your commit message, e.g. `git commit -a -m "Copy of commit "` – Leon Sep 23 '16 at 16:28
  • I'll argue that `git cherry-pick -x` is automatic :) – KcFnMi Sep 23 '16 at 17:02
  • @KcFnMi If you need to perform this operation regularly then it can be made automatic too, with a simple script. – Leon Sep 23 '16 at 17:15
  • That's cool. It'll be interesting to have more details about this on the answer. – KcFnMi Sep 23 '16 at 17:22