cHao
cHao

Reputation: 86525

How can I "clean up" branches locally, without breaking everything for others?

I'm pulling changes from someone else's repository (let's call them 'gitnoob' for cathartic reasons) that has stuff all intermingled. They were apparently working in their main branch for everything at first and then learned about branches. It looks a bit like this:

                  d - f <--- stuff
                 /   /
A - b - 1 - c - 2 - E <--- dev

The numbers are commits that should have been in another branch, and may break things if I merge them into my own dev branch. (I'll pull them from upstream/dev later -- upstream being our shared parent repository -- once they're merged in there.) The lowercase letters are commits that should be part of stuff, and the uppercase ones are commits legitimately merged in to dev.

Ideally, I'd like to clean this up on my end -- to have something like this locally:

  b - c - d - f <--- stuff
 /           /
A --------- E <--- dev

Now, stuff having all the stuff-related changes is going to happen anyway, because gitnoob/stuff will also include all the differences between upstream/dev and gitnoob/dev to that point (and the legitimate dev ones will already be in my dev branch). The problem is, that means stuff will also have commits 1 and 2, which may well break things.

I need to be able to pull changes from gitnoob/stuff without massive amounts of hassle (and, if at all possible, without getting 1 and 2 back in there till they show up upstream), and have them pull changes from me without anything on their end getting reverted or deleted.

How do I do this? Or am I just stuck with 1 and 2 in stuff?

Upvotes: 2

Views: 194

Answers (2)

Karl Bielefeldt
Karl Bielefeldt

Reputation: 49078

So basically, you want a private version of stuff that reverts 1 and 2, but your own public version of stuff that still includes it for gitnoob to pull from. There's no seamless way to do that, but one way to accomplish it is by introducing a couple new branches:

...d-f <---stuff-upstream
      \
       g <---reverted-stuff
        \
         h <---my-stuff

What you do is make a reverted-stuff branch that reverts 1 and 2. When you want to make changes that are shared with gitnoob, you branch from reverted-stuff to make my-stuff. Change and commit as normal on my-stuff. You should be able to merge your dev into my-stuff as well.

When you're ready to share the changes, rebase my-stuff back onto stuff-upstream using git rebase --onto stuff-upstream reverted-stuff my-stuff. That will remove your reverts in g and make it look like my-stuff was branched directly from stuff-upstream, allowing gitnoob to pull without fear.

When you pull from gitnoob, pull into stuff-upstream, then merge it down into reverted-stuff. That merge will automatically reapply g, where you reverted 1 and 2. Then you can branch a new my-stuff off of reverted-stuff.

That being said, if 1 and 2 are really as problematic as you say, you will be doing gitnoob a favor by getting it out of his branch as well. If it's not that bad, there's really no reason to go through all this.

Upvotes: 1

eckes
eckes

Reputation: 67067

In that situation, I'd recommend to leave the past as it is and try to do it better in the future.

What's the benefit of taking b and c out of dev and having them only in stuff? Since stuff was branched off dev after c, the commits are contained in stuff anyway.

I'm tempted to do such things occasionally too but usually I end up thinking so what? This is especially the case for those commits made when I learned Git and switched over from SVN. Something went wrong. Okay. But it works. So don't touch it.

Version control is a tool, not an end in itself. You put some code in your repo. That's the precious thing. Not the – maybe – intermingled history of the repo.

You could fix the branches locally, but when it comes to merging things back from upstream or pushing changes there, you'll get in trouble.

Upvotes: 1

Related Questions