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-1ID.
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.
Answer from VonC on Stack OverflowThis 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.
How to merge a specific commit in Git - Stack Overflow
git - Squash all my commits into one for GitHub pull request - Stack Overflow
Merge Commit, Squash, or Rebase: how do you close Pull Requests on GitHub?
How do I rebase multiple merge commits into a single one?
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-1ID.
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.
You can use git cherry-pick to apply a single commit by itself to your current branch.
Example: git cherry-pick d42c389f
Just a simple addition to help someone else looking for this solution. You can pass in the number of previous commits you would like to squash. for example,
git rebase -i HEAD~3
This will bring up the last 3 commits in the editor.
ok I figured it out ...
First I had to write git rebase -i xxxxxxxxxxxxxxxx where xxxxxxxxxx is the SHA of the commit upto which I've to squash. Then in Notepad I edited the first as pick and rest of all as squash. Then a new notepad window will come and there in the first line I typed the name of my new commit.
And then I had to do a force push :
git push --force origin master
When Merging a Pull Request on GitHub, you mainly have three options: merge commit, squash or rebase.
Is there anything wrong with always doing a merge commit? Well, there isnโt right or wrong here, but considering the other strategies will likely bring you some benefits.
I made a video about it: https://www.youtube.com/watch?v=rFRtsiQEJZw
In the video, I will go into detail about the three strategies, and I will also do a "live demo" with GitHub stickers and JS pins, if you're curious I'd recommend you to watch the video, otherwise you can find the full-text content here below.
Merge Commit
Merge commit is probably the most common as itโs the default option on GitHub and also the default behavior when you manually use git merge.
The history of all your commits remains untouched and on the main branch, you see an additional commit that merges all your branch content.
The biggest advantage is that you can easily track down the exact commit where a line has been modified, as long as there arenโt too many commits.
The downside is that when multiple commits are on multiple branches, the history quickly becomes really tangled, and following the path of a change can be quite a challenge.
Squash merge
The question is, do you really need to keep track of every single commit? Including typos, missing files, formattingโฆ if the answer is no, then you should consider Squash merge.
When squashing a merge, the result is that you get rid of all commits on the branch and only add a single commit on main with all the content.
As a result, the history is much cleaner and while working on a branch you can do all the commits you want since you know that with the squash all your sins will be forgotten. Kind of.
Who doesnโt like squash merge, usually brings up the fact that youโre losing a lot of commit history, but itโs up to you if you think commits on a branch are valuable when reviewing old activity or rather is just noise.
Rebase
A third way is that you donโt really need a commit that indicates a merge took place, and you still want to end up having all commits in a single, straight line.
Merge commit has all tangled lines plus an extra commit, Squash is a straight line but loses the history so here comes Rebase, which keeps the history AND the straight line AND doesnโt require an extra commit for the merge.
Does this make Rebase the best strategy ever? Well... actually not necessarily, because it has some potentially destructive side effects.
If you get a merge conflict during a rebase, itโs fairly easy to unintentionally lose parts of your code code and if you need to catch up on multiple commits you might end up resolving a merge conflict for every single commit, rather than just one in the other merge strategies.
My two cents
After this overview, what do you think? Let me know in the comments!
In my opinion, if branches donโt stay open for a long time, squash merge is a good option, also Iโm not a fan of rebase because itโs too easy to make huge mistakes. But before deciding which strategy to apply you should take some considerations.
For example, how often do you and your team have to look back at old commits? How many members are on the team? Does your CI need the full commit history?
Think about it, talk with your team, and you can find together the best strategy for your own use case.
Actually, a good strategy could be subscribing to my YouTube channel if you like my content!
Config
If you want to enforce only some merge strategies on GitHub, head over to the settings of your repository and scroll down a little bit.
Here you will find three sections to allow merge commit, squash, or rebase in your pull requests.
If you keep only one selected, all PRs in your repo will be merged with that specific strategy.
For the first two, you can also define the default commit message that can take information from the PR or the commits in the branch in case of a squash.
As you can see rebase doesnโt have this option and the reason is simple. As we just saw, rebasing does not create an extra commit for the merge, so there is nothing to do here. The existing commits are simply moved to the head of your branch.
Since youโre already on this page, if you scroll down a little bit more you might also want to check this flag to automatically delete branches after a PR is merged.
Closing
If you have any preference or you want to share your experience, please leave a comment, I'll be really happy to hear from you!
With that said, happy new year, may it bring you a lot of merged PRs and no merge conflicts!
-
Basically "squash" multiple merge commits of different branches into one super branch and one final merge commit with all changes?
I was contributing to my first open source repo, and I opened a pull request solving an issue. I had fixed the issue in like 5 or 6 commits, but then the maintainer of that repo somehow squashed all of them into one commit. How can I do that?
The notification that popped up on GitHub said something like
<maintainer> force-pushed the <issue_branch> from 015b7f3 to fcc9fcd
and he said that he "rebased from the main branch"? What exactly did he do and how can I do that?