0

I have a simple branch with multiplpe changes:

Master ---A---B---C
                   \
              Foo   E---F---G---H

Now I need to merge into the Master only a part of my changes. I am new to git ( currently using it with SourceCode on Windows ), and was thinking of doing it like this:

Master ---A---B---C---?---J---?---?---
                   \     /
              Foo   E---G'
                         \
                    Bar   F'---H'---

I need only certain parts from the branch. I've been working on 4 different manufacturer APIs to implement. Now, only 1 needs to go in production and the rest are on hold. Let's say there are total of 19 files modified, but I only need 7 of them. Now, I need to split those 7 away, synchronize with the master and push as a different branch, so that the CTO can merge them into Master later on.

Is that the way to do it? And how do I do it correctly?

Peon
  • 7,216
  • 7
  • 45
  • 87
  • In the picture, all the changes went into master. Maybe you wanted only "E F" on `Foo`, and "G H" moved to `Bar`? – choroba May 23 '16 at 09:44
  • Exactly, I'm still struggling with these type of diagrams. – Peon May 23 '16 at 09:46
  • You can probably use `git --cherry-pick` for this – Vishwanath May 23 '16 at 10:18
  • Running over the possibilities, I think this is not that easy as I mentioned. The changes, I need to commit are in multiple commits in the branch, so I would need part of E, part of G and part of H to split down. Basically, I need a way to push only certain files from my branch into a new branch, that will be pushed into master later on this day. – Peon May 23 '16 at 10:35
  • `git checkout Foo;git reset E --hard;git cherry-pick G;git checkout -b Bar Foo;git cherry-pick F;git cherry pick H` Foo is ABCEG', Bar is ABCEG'F'H'. – ElpieKay May 23 '16 at 12:15

1 Answers1

1

If we breakdown your problem, you need to:

  1. Split 4 (E,F,G,H) commits from Foo into 2 branches, Foo will have only: E, G, but Bar will have all 4, E -> G -> F -> H.
  2. Remove some commits : i.e. on Foo, remove commit F and H.
  3. I am not sure if you want to "Re-order" the commits on the branch Bar, i.e. have E,G,F,H --> I am assuming this solves no purpose, so I will leave it out of my answer.

There are many ways of doing it, but I will keep it to the simplest flow that I can think of, since you are new to git. so, let us look at splitting the branch:

From your current Foo (head = H) do git checkout -b Bar This will create the branch Bar with commits E, F, G, H

Now, there are two ways you can reset your Foo branch:
#1 Discard Foo and re-create it git branch -D Foo (to delete from local) git push origin :Foo (to delete from remote, if you have already pushed it)

Then you need to create a new Foo from commit "C" of your master:

git checkout -b Foo <CommitIdShaForC>

Then you can cherry-pick commits E and G either from git gui by doing gitk Bar and then right clicking on the commit and choosing cherry-pick, or from console by:

git cherry-pick <Commit Id for E> <Commit Id for G>

In case of merge issues, look at this answer

#2 Revert commits from Foo If you don't mind having history of F and H in your foo, you can simply revert them in git, essentially git creates a reverse patch of your commits F and H and applies them as new commits:

  • You are on branch Foo and it has E -> F -> G -> H
  • git revert F
  • Your branch should now show E -> F -> G -> H -> F' where F' is undoing what the commit F added
  • git revert H would lead to: E -> F -> G -> H -> F' -> H' whose end result in the source code would be: same as having only commits E and G.

Alternatively still, you can use the --no-commit flag on git revert to revert both F and H in 1 commit:

git revert --no-commit F
git revert --no-commit H
git commit -a -m "reverting commits F and H"

This would lead to:

E -> F -> G -> H -> I where I is the commit which undoes F and H

#Update 1 After writing a lengthy answer, I see that OP wants to have "part of the commits" into few branches. For this case, I would highly recommend an interactive rebase so that the commits can be split. Please refer to the official documentation about git rebase, in particular the section about "Splitting Commits". Also, I think you will find this question particularly helpful

Community
  • 1
  • 1
dubes
  • 4,504
  • 3
  • 31
  • 43
  • As I wrote in the comment, I need only certain parts from the branch. I've been working on 4 different manufacturer APIs to implement. Now, only 1 needs to go in production and the rest are on hold. Let's say there are total of 19 files modified, but I only need 7 of them. Now, I need to split those 7 away, synchronize with the master and push as a different branch, so that the CTO can merge them into Master later on. – Peon May 23 '16 at 10:47
  • @DainisAbols updated my answer with hints about how you can split commits. Also your comment adds significant clarity to your question, can you please edit it so that others can find it useful. – dubes May 23 '16 at 10:50
  • @DainisAbols : do take a look at the question thread I attached, I think that is eventually what you want to do. – dubes May 23 '16 at 10:53
  • I ended up making a branch, from the commit `E` and comparing it with `H`. I took only the necessary changes and did a rebase with them. That way I got the right data in a separate branch that was successfully merged into master. Just letting know. – Peon May 24 '16 at 14:05
  • That was tough... the situation your mentioned was indeed a difficult one. I hope you don't have to face more like them... but if it comes to it, reply to this comment and we can move it to a chat and try to figure out git interactive rebase – dubes May 24 '16 at 14:47