I am working on one project which has three branches on git. (Master,stag,dev). Master is main branch and stag is branch created from Master. And dev is branch created from stag. Now I have pushed my code changes to dev. I have pushed two commits(#com1,#com2). And I want to merge dev and stag with only one commit(#com1) and without my latest commit(#com2).How should I proceed?
CodePudding user response:
Makes no sense. If you added com1 and com2 to dev, then dev is com2. So to speak of merging dev "without" com2 is nonsense.
On the other hand, if the goal is to merge com1 into stag, then just do it. Merges merge commits, not branches; it is mere habit and convenience that causes us to give a branch name as the merged commit.
git switch stag
git merge <SHA of com1>
CodePudding user response:
In git, a "branch" is just a pointer to a commit, and history is formed by commits pointing to other commits as their "parents". A merge commit is one with two or more parents.
With that in mind, we can draw approximately what you have:
... A <--B <--C <--D <--E <--com1 <--com2
^ ^ ^
[master] [stag] [dev]
When we say "merge dev to stag" what we mean is to create a new merge commit with parents of the current tips of those branches, and point "stag" at that merge commit:
<-------------
/ \
... A <--B <--C <--D <--E <--M <-[stag]
^ \ /
[master] <--com1 <--com2 <-[dev]
Or possibly to "fast-forward" the branch, so that "stag" simply points at the same history as "dev":
... A <--B <--C <--D <--E <--com1 <--com2
^ ^
[master] [dev,stag]
Note that in both cases, all we used "dev" for was to find the commit "com2"; git merge dev
and git merge com2
would do the same thing. So we can equally merge com1
:
<------
/ \
... A <--B <--C <--D <--E <--M <-[stag]
^ \ /
[master] <--com1 <--com2 <-[dev]
Or fast-forward to it:
... A <--B <--C <--D <--E <--com1 <--com2
^ ^ ^
[master] [stag] [dev]
Note that we can only do this because there is nothing else between "E" and "com1" - we can't say "only merge this one commit", because the history of a commit is part of its identity. So in this example, we can't merge "com2" without "com1" coming along as well, because it is the parent of "com2". The only way we could do that is by creating a new commit with the same changes as com2, but a different history - look up "cherry-pick" and "rebase" for information on how to do that.
CodePudding user response:
Get #com1 commit hash and use cherry-pick option like this:
git checkout stag
git cherry-pick {commit hash}
git push