1

Let's say some dev work in his branch and do those commits:

A -> B -> C -> D -> E

I'm the reviewer and I notice that in commit B some files have been changed that shouldn't be.

I'm trying to find the best way to solve that case, I would like to do:

A -> B -> X -> Y -> C -> D -> E

where:

  • X is a revert of B
  • Y is B without the unneeded changes

I was thinking to do what is following but I know it wouldn't look exactly the same:

  • git checkout -b on B
  • revert B in X
  • do B in a better way in Y
  • merge C D E in my branch
  • put everything back on the dev branch

Does the above work? Is this the best way to do it or is there a better way?

NOTE: I'm interested to hear any solution involving rewritting the history as well.

plus-
  • 45,453
  • 15
  • 60
  • 73

4 Answers4

4

Since this branch has been pushed upstream and made public - do not rewrite its history. That will break other developers branches.

What you should do is:

A -> B -> C -> D -> E -> X -> Y

Keep the history up till E (which I assume is HEAD). Then git revert B which will revert the bad commit as commit X. Then fix it with your commit Y.

Alternatively, you can git revert -n B, which will wait with the commit and allow you to edit the commit, thus having all the fixes in a single commit (X only, no Y). This is the more elegant way to handle this issue.

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
  • But what if C D and E all alter some stuff in B? – plus- Dec 04 '12 at 12:58
  • Either way you'll have a conflict to fix. In your method that would happen in the rebase phase. In my method it'll happen before you commit the revert. – Yuval Adam Dec 04 '12 at 12:59
3

revert of B itself is a separate commit as you yourself have pointed out (X) and (Y) is again an extra commit without unneeded files. why don't you just remove unneeded file and commit it once without reverting the original commit? Like this: A -> B -> C -> D -> E -> Z where commit Z removes unneeded files if they are still there.

Peyman
  • 83
  • 2
  • 8
  • Ok the question was not clear enough sorry, in fact those uneeded files where files who existed previously and didn't required a change so I can't do Z. I'll fix the question – plus- Dec 04 '12 at 13:02
  • then check here: http://stackoverflow.com/questions/953481/restore-a-deleted-file-in-a-git-repo – Peyman Dec 04 '12 at 13:13
1

So I found a solution which fits my need using rebase -i (I don't care rewriting history in this feature branch case)

  • git rebase -i A (the commit before B)
  • git reset HEAD^1 filename (do this as much as you need on files that didn't need a change)
  • git commit --amend
  • git rebase --continue

I like it because it does literraly what I needed: remove by hand files I wanted to remove from a commit, and no merge.

plus-
  • 45,453
  • 15
  • 60
  • 73
  • 1
    Happy to hear this is the case with your feature branch. However, it should be stressed that this is *not encouraged* for branches that are public, and that other developers push to and pull from. Rebasing **breaks** branches for other developers and this should be very clear. – Yuval Adam Dec 04 '12 at 17:30
0

Yuval's answer is the correct approach for the development of this branch, but if this is a feature branch that is being worked on separately from the main branch and will be merged in future (e.g. these commits are on dev and the main branch is master):

  1. Revert in X and fix in Y as per Yuval's answer
  2. Develop as normal
  3. When coming to merge the feature, run git rebase -i master
  4. Move X and Y to immediately follow B
  5. Optionally, mark X and Y as fixup and they will be squashed into B
  6. Fix any conflicts in C, D and E

You now have a local dev branch with the commits in the order you want. You can now merge this branch into master and delete the dev branch; this way you have the clean history you desire without breaking anyone's development work.

cmbuckley
  • 40,217
  • 9
  • 77
  • 91