Reputation:
I think what I am looking for is the oldest shared ancestor of two branches, or something like that, this question seems to touch on it: Finding a branch point with Git?
But instead of the diagram in the OP, this is more what I am looking at:
-- I -- I -- I -- I -- I -- I -- I (integration branch)
\ \ /
\ \ /
F -- F -- F -- F (feature branch)
My question is - if we checkout a feature branch from integration and make some changes and some commits, and then we update/merge with integration a few times as we go. Aka, commit commit, merge with integration, commit commit, merge with integration, etc. If we then do a git reset --soft <integration>
, is that going to reset it to the commit on integration when git checkout
was used, or will it simply reset it to the point where the last git merge
with integration occurred?
The goal is so that I can make my feature into one big commit. If the git reset --soft
only goes back as far as the last git merge with integration, then my feature might have 100s of commits, which is no bueno, and I will need another technique.
Upvotes: 3
Views: 229
Reputation: 490078
You can use git reset --soft
, but there's something else you must do—or rather, not do—first.
The goal is so that I can make my feature into one big commit.
In that case, make sure you don't start with:
-- o -- A -- B -- C -- D -- E -- IM <-- integration
\ \ /
\ \ /
F1 -- F2 - FM - F4 <-- feature
Note that I have replaced the individual letters here so that I can talk about particular commits. The two most interesting commits, as far as Git itself is concerned, are F4
, which is the tip commit of the branch named feature
, and IM
, which is the tip commit of the branch named integration
.
The commit labeled FM
is not a problem, even though it is a merge commit. The commit labeled IM
is a problem. That's because this commit is reachable from the tip of integration
. For (much) more on the concept of reachability in general, see Think Like (a) Git. Whenever commit IM
itself is reachable by starting at the commit to which integration
points, and working backwards (leftwards), so are all commits that commit IM
itself reaches. Commit IM
leads back to both commit E
(not a problem) and F4
(problem!).
If you eliminate commit IM
, so that you have:
-- o -- A -- B -- C -- D -- E <-- integration
\ \
\ \
F1 -- F2 - FM - F4 <-- feature
you can now git checkout feature
and run git reset --soft integration
, resulting in this:
-- o -- A -- B -- C -- D -- E <-- feature (HEAD), integration
\ \
\ \
F1 -- F2 - FM - F4 [abandoned, but remembered as feature@{1}]
Your index and work-tree are unchanged from when you had commit F4
checked out, though, so you can now run git commit
to turn the current index into a new commit. The name feature
will now point to the new commit:
F <-- feature (HEAD)
/
-- o -- A -- B -- C -- D -- E <-- integration
\ \
\ \
F1 -- F2 - FM - F4 [feature@{1}]
The snapshot for new commit F
will match that for commit F4
:
git diff feature@{1} feature
will print nothing at all. But the parent of new commit F
is existing commit E
. (Commit F
also has a new author and committer and corresponding "now" time stamps, which also distinguish it from F4
.)
Upvotes: 1
Reputation: 1329712
Each time you are merging feature back to integration
, you are moving integration
HEAD (which now reference the new merge commit)
You need to mark integration
before doing your feature
branch and your merges in order to get back to it.
One possible marker would be origin/integration
: that last time you fetch integration
).
Another one is git merge-base --fork-point
(based on reflog
, so unreliable) or some diff between git rev-list --first-parent
of both branches.
In any case, your git reset --soft
would have to use that marker, not the local integration branch.
Upvotes: 0