I have forked a branch from a repository in GitHub and committed something specific to me. Now I found the original repository had a good feature which was at HEAD
You can use git cherry-pick to apply a single commit by itself to your current branch.
Example: git cherry-pick d42c389f
In my use case we had a similar need for CI CD. We used git flow with develop and master branches. Developers are free to merge their changes directly to develop or via a pull request from a feature branch. However to master we merge only the stable commits from the develop branch in an automated way via Jenkins.
In this case doing cherry-pick is not a good option. However we create a local-branch from the commit-id then merge that local-branch to master and perform mvn clean verify(we use maven). If success then release production version artifact to nexus using maven release plugin with localCheckout=true option and pushChanges=false. Finally when everything is success then push the changes and tag to origin.
A sample code snippet:
Assuming you are on master if done manually. However on jenkins, when you checkout the repo you will be on the default branch(master if configured).
git pull // Just to pull any changes.
git branch local-<commitd-id> <commit-id> // Create a branch from the given commit-id
git merge local-<commit-id> // Merge that local branch to master.
mvn clean verify // Verify if the code is build able
mvn <any args> release:clean release:prepare release:perform // Release artifacts
git push origin/master // Push the local changes performed above to origin.
git push origin <tag> // Push the tag to origin
This will give you a full control with a fearless merge or conflict hell.
Feel free to advise in case there is any better option.
Let's say you want to merge commit e27af03
from branch X to master.
git checkout master
git cherry-pick e27af03
git push
The leading answers describe how to apply the changes from a specific commit to the current branch. If that's what you mean by "how to merge," then just use cherry-pick as they suggest.
But if you actually want a merge, i.e. you want a new commit with two parents -- the existing commit on the current branch, and the commit you wanted to apply changes from -- then a cherry-pick will not accomplish that.
Having true merge history may be desirable, for example, if your build process takes advantage of git ancestry to automatically set version strings based on the latest tag (using git describe
).
Instead of cherry-pick, you can do an actual git merge --no-commit
, and then manually adjust the index to remove any changes you don't want.
Suppose you're on branch A
and you want to merge the commit at the tip of branch B
:
git checkout A
git merge --no-commit B
Now you're set up to create a commit with two parents, the current tip commits of A
and B
. However you may have more changes applied than you want, including changes from earlier commits on the B branch. You need to undo these unwanted changes, then commit.
(There may be an easy way to set the state of the working directory and the index back to way it was before the merge, so that you have a clean slate onto which to cherry-pick the commit you wanted in the first place. But I don't know how to achieve that clean slate. git checkout HEAD
and git reset HEAD
will both remove the merge state, defeating the purpose of this method.)
So manually undo the unwanted changes. For example, you could
git revert --no-commit 012ea56
for each unwanted commit 012ea56
.
When you're finished adjusting things, create your commit:
git commit -m "Merge in commit 823749a from B which tweaked the timeout code"
Now you have only the change you wanted, and the ancestry tree shows that you technically merged from B.
Let's try to take an example and understand:
I have a branch, say master, pointing to X <commit-id>, and I have a new branch pointing to Y <sha1>.
Where Y <commit-id> = <master> branch commits - few commits
Now say for Y branch I have to gap-close the commits between the master branch and the new branch. Below is the procedure we can follow:
Step 1:
git checkout -b local origin/new
where local is the branch name. Any name can be given.
Step 2:
git merge origin/master --no-ff --stat -v --log=300
Merge the commits from master branch to new branch and also create a merge commit of log message with one-line descriptions from at most <n> actual commits that are being merged.
For more information and parameters about Git merge, please refer to:
git merge --help
Also if you need to merge a specific commit, then you can use:
git cherry-pick <commit-id>
'git cherry-pick' should be your answer here.
Apply the change introduced by an existing commit.
Do not forget to read bdonlan's answer about the consequence of cherry-picking in this post:
"Pull all commits from a branch, push specified commits to another", where:
A-----B------C
\
\
D
becomes:
A-----B------C
\
\
D-----C'
The problem with this commit is that git considers commits to include all history before them
Where C' has a different
SHA-1
ID.
Likewise, cherry picking a commit from one branch to another basically involves generating a patch, then applying it, thus losing history that way as well.This changing of commit IDs breaks git's merging functionality among other things (though if used sparingly there are heuristics that will paper over this).
More importantly though, it ignores functional dependencies - if C actually used a function defined in B, you'll never know.