git reset --soft - does it go back to git checkout point or to the last git merge point?
git reset --soft - does it go back to git checkout point or to the last git merge point?
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?
git reset --soft <integration>
git checkout
git merge
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.
git reset --soft
git reset --soft
git merge-base --fork-point
2 Answers
2
Each time you are merging feature back to integration
, you are moving integration
HEAD (which now reference the new merge commit)
integration
integration
You need to mark integration
before doing your feature
branch and your merges in order to get back to it.
integration
feature
One possible marker would be origin/integration
: that last time you fetch integration
).
origin/integration
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.
git merge-base --fork-point
reflog
git rev-list --first-parent
In any case, your git reset --soft
would have to use that marker, not the local integration branch.
git reset --soft
yeah that makes sense, I guess
git reset --soft <thing>
, finds <thing> in the current branch and undos all commits back until that point. So it's just a matter of finding the right <thing> to go back to.– Olegzandr Denman
Sep 2 at 2:18
git reset --soft <thing>
@OlegzandrDenman Yes, that is the idea.
git reset --soft
removes commits, but keep the final content intact (work tree and index). But you still need where to go back to.– VonC
Sep 2 at 2:20
git reset --soft
@OlegzandrDenman the only ways I know of are listed in the post you reference in your question, and that I allude to in my answer: merge-base of rev-list.
– VonC
Sep 2 at 2:22
@OlegzandrDenman Not exactly: see stackoverflow.com/a/20966716/6309. Wait... this answer is not selected?
– VonC
Sep 3 at 21:42
@OlegzandrDenman Which ever answer seems clearer to you is the right one. I just forgot about this question, and didn't realized that since I answered it, torek came along.
– VonC
Sep 3 at 21:48
You can use git reset --soft
, but there's something else you must do—or rather, not do—first.
git reset --soft
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
.
F4
feature
IM
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!).
FM
IM
integration
IM
integration
IM
IM
E
F4
If you eliminate commit IM
, so that you have:
IM
-- 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:
git checkout feature
git reset --soft integration
-- 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:
F4
git commit
feature
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
:
F
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
.)
F
E
F
F4
Thanks for this - I will have to read about reachability, but I guess on the face of it I don't quite see why commit
IM
is a problem?– Olegzandr Denman
Sep 2 at 2:30
IM
If you add a new commit atop commit
IM
, the new commit will point back to IM
, so that git log
will first show commit F
, then IM
, then—in some order—all of A-B-C-D
and F1-F2-FM-F4
. The reason is that Git traverses both chains (in backwards order, but otherwise simultaneously).– torek
Sep 2 at 5:41
IM
IM
git log
F
IM
A-B-C-D
F1-F2-FM-F4
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
git reset --soft
moves the current branch where you tell it to move it. It does not do any search or decision by itself. You are looking forgit merge-base --fork-point
.– axiac
Sep 2 at 8:04