0

I have a test branch with commits a1, a2, a3, a4. I would like to take the changes to the master branch but only in one commit instead of four. So I did:

git checkout master
git merge -Xtheirs test
git rebase -i a1

squash a4
squash a3
squash a2
pick a1

So on master branch I got a commit b1 that included changes from a1, a2, a3, a4. This worked fine, when done for the first time. Then I continued with my testing branch, adding commits a5, a6, a7, a8. I checked out to master and merged again - I had to resolve the conflicts which is weird because a5 is a continuation of a4 and therefore of b1 as well. Note that git diff on a4 and b1 did not output any differences. Then I tried to rebase from a5 and there were even more conflicts.

So it looks that git rebase is not what I need. After joining the commits, git considers a4 and b1 as different commit objects with different history and what is worse even different position in the graph.

I would like something like:

b0 --- b0
|       |
a1      |
|       |
a2      |
|       |
a3      |
|       |
a4 ---- b1
|       |
a5      |
|       |
a6      |
|       |
a7      |
|       |
a8 ---- b2
|       |   
a9      |
|       |
... --- b3

Is that even possible?

Note, I could create a branch for every group of commits, i.e. one for a1, a2, a3, a4 then do the merge and rebase with master and create another branch from b1 for commits a5, a6, a7, a8 and then do the merge and rebase with master to get b2 and so on. But this is not what I want - it is not desirable to have one branch per day. I want to have only two branches - a test branch with all the commits and a master branch with a rougher granularity. So that when I push master, they would not see every little change I make.

Dávid Natingga
  • 839
  • 3
  • 13
  • 30
  • You want to rebase before you merge. And yes, rebasing will create new commits (at different positions in the graph). You will see the old commits if the have been merged earlier or are referenced by another ref. – knittl Aug 03 '12 at 17:39
  • But before merging on the master branch there will not be any commits to rebase. I do not want to rebase the test branch - I want to keep it the way it is. – Dávid Natingga Aug 03 '12 at 19:51
  • Then you will get different commits. – knittl Aug 03 '12 at 20:01
  • I do not mind having different commits. However, I would like if there were no conflicts and there is a justified reason for that - a4 is exactly the same as b1. So all changes from a4 on should not contradict the changes from b1 on - they are the same. The only difference is that in a master branch they are in bunch instead of being separated as in a testing branch. Do you therefore say that it is not possible to have two branches: one with a finer granularity (e.g. a testing branch) and the other with a rougher granularity (e.g. a master branch)? – Dávid Natingga Aug 03 '12 at 22:04
  • Every time you rebase, you create a new line of history. A commit can exist in as many branches as you want it to, but it has to be the exact same commit (no rebase!). `git merge --no-ff` (as suggested by Mattias in the answers) looks like a good candidate. When you view the log with `--first-parent` option you would only see the merge commits (one per feature). Also, you should not see conflicts when merging with the `-Xtheirs` strategy option. Maybe we can take this discussion to [chat]? – knittl Aug 04 '12 at 06:46

2 Answers2

4

Maybe you want to use the --no-ff option with git merge? that way you will always get a merge commit instead of git doing a fast forward merge of the commits. In your case then b0, b1, ... would be merge commits.

EDIT:It is not possible to have only b0, b1 commits on a master branch without merge conflicts. But the above is a good alternative if it is not necessary to hide the intermediate commits. In General, you either do rebase and/or cherry-pick and deal with conflicts or push all the commit objects and do not have to deal with conflicts.

Dávid Natingga
  • 839
  • 3
  • 13
  • 30
Mattias Wadman
  • 11,172
  • 2
  • 42
  • 57
  • Thank you Mattias for your answer, I tried `git merge --no-ff`, it caused conflicts just like `git merge`. I do not think that it makes git recognize that b1 and a4 are the same. – Dávid Natingga Aug 03 '12 at 22:10
  • @dt1510, you need to `merge --no-ff` always, from the first time; never to `rebase` (in this particular case) – Piotr Findeisen Aug 04 '12 at 05:34
  • Thanks. I tried everything from the beginning and it worked without any merge conflicts when --no-ff option was used. But Master branch still contained commit objects a1, a2, a3, a4, not only b1. As knittl said with `git log --first-parent` I could see only b1, b2, ... changes. But with `git log` anybody could see on the master branch also those a1, a2, a3, a4 which is not what I wanted. Basically, I want to hide my small changes from others, I do not even want to allow them to see it because they would not approve them. But if they can see only b1, b2, ... everything would look fine for them. – Dávid Natingga Aug 06 '12 at 17:44
  • Ok seams a bit broken development model to use git for, why anyone care about anything but the end result commit? anyway i think you might want to do something like this http://stackoverflow.com/questions/10769389/git-release-branch-with-squashed-commits/10774917#10774917 that will make a new commit with the same tree as in the branch but it will only have on parent (not a merge) so other people wont see your "private" commits if you push it somewhere. – Mattias Wadman Aug 06 '12 at 21:42
1

While on master, you can git cherry-pick a1..a4 and then squash these new commits in the master. This will leave the commits in the test branch untouched and lets you push the master so that the others would not see every single change you make (as per your requirement)

Of course, in this case b1 and a4 will be two different commits. In fact, b1 and a4 will never be the same commit. If you want your graphical tool to point to b1 from a4, you'd have to use a --no-ff merge as Mattias has mentioned above.

thameera
  • 9,168
  • 9
  • 37
  • 38
  • So if I understand correctly, everything comes down to two options: 1. I can hide changes from others, but then a4 will be different from b1 for git (even if their content is the same - `git diff` outputs nothing). But this will cause merge conflicts. 2. Or I can still keep the test and the master branch compatible without merging conflicts (e.g `git merge --no-ff`) but then everybody would see in my master branch everything that I put in my testing branch. – Dávid Natingga Aug 06 '12 at 17:47
  • Yes. If you want to hide the commits and retain the testing branch, you will have to use the cherry-pick method. – thameera Aug 07 '12 at 04:53