2

I got a very messy branch, with a lot of commits, that I used for some experimentations.
It turns out that I want to keep a large part of this work, but its really need to be refactored and cleaned up.

So I'd like to copy all these modifications to a new branch, without history and without committing.
That way, I could clean it up, start a proper feature branch and remove the messy one.

Before:

          D - E - F
         / 
A - B - C


After:

          D - E - F
         / 
A - B - C
         \
          DEF (uncommitted)

I didn't find the way to do that, help would be really appreciated.

Thanks :-)

bgaze
  • 980
  • 1
  • 8
  • 24
  • Note: until you actually *commit* this new `DEF` commit—the `git commit` after the `git reset --soft` in VonC's answer—the new branch name, whatever may be, will identify commit `C`. The uncommitted files will be in your work-tree and perhaps also have already replaced the commit-`C` copies of file in your index. (This depends on whether you have used `git reset --soft` as n VonC's answer, or `git reset --mixed` / default as in knittl's.) – torek Dec 07 '19 at 20:30

3 Answers3

2

You could use a git reset --soft C, from your current branch: that would preserve the working tree

git switch oldMessyBranch
git switch -c newBranch

# Or, in one line:
git switch -c newBranch oldMessyBranch

# Then:
git reset --soft C
git commit -m "new squashed branch"

Note: with Git 2.23+, you should use the new (still experimental) command git switch.

From there, you can add the content and create a new branch.

As I mentioned in "Practical uses of git reset --soft?"

So, each time:

  • you are satisfied with what you end up with (in term of working tree and index)
  • you are not satisfied with all the commits that took you to get there:

git reset --soft is the answer.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
2

git reset to the rescue!

git checkout -b newbranch F
git reset C

This will create a new branch with the content of F, then set the branch's tip to commit C with all changes still in the working tree. Without any arguments, it defaults to --mixed mode, so the changes will be unstaged and you can them add and commit them as you like.

(With --soft all changes are automatically added to the staging area)

knittl
  • 246,190
  • 53
  • 318
  • 364
1

Say you want to copy the changes to branch foo. You have several options.

git diff C F > foo.patch
git checkout foo
git apply -3 --reject foo.patch

or

git checkout foo
git cherry-pick -n D
git cherry-pick -n E
git cherry-pick -n F

or

git checkout -b temp C
git merge --squash F
git commit
git checkout foo
git cherry-pick temp
git branch -D temp

There are some other variations. The key is to get the diff first and then apply the diff.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53