Reputation: 86525
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
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
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