Combining multiple commits before pushing in Git
Based on my understanding, if I use git rebase -i master
, then later I still need to git push origin
Before we go any further, run:
git rev-parse master
and:
git rev-parse origin/master
You'll see two SHA-1s. If those two SHA-1 values are the same, the two rebase commands will do the same thing. If not, they will do different things.
<upstream>
argument is usedThe <upstream>
argument to git rebase
has two purposes:
<onto>
argument, it selects the starting point for the sequence of cherry-picks.(Remember, the syntax here is git rebase [options] [<upstream> [<branch>]]
so master
and origin/master
in your examples provide an <upstream>
. You must use the --onto
option to provide an <onto>
, and you're not doing so, so the <upstream>
provides it instead.)
To see which commits are selected, you can use git rev-list
(or its more-verbose equivalent, git log
). The actual commits selected for rebasing are those that are contained in the current branch but are not contained in the <upstream>
. That is:
git rev-list master..HEAD
or:
git rev-list origin/master..HEAD
respectively. (Replace rev-list
with log
to see them in detail, or log --oneline
to see them as one-line descriptions.)
The rebase
command works by copying commits, then setting the branch name to point to the new, tip-most copy.
If you use the interactive version, it puts the commit IDs and instructions into a file that you can edit. Otherwise it just goes through all the commit IDs from the above git rev-list
commands, in order.
Before starting the sequence of cherry-picks, rebase
detaches HEAD
at the <onto>
commit. That is, the <onto>
commit is the starting point for the copies.
Then, for each commit ID, rebase
essentially runs git cherry-pick
(if you're using the interactive version there's no "essentially" about it, it actually uses git cherry-pick
, with some modifications based on your instruction editing). This copies the original commit to a new one at the new branch-tip. As each commit is copied, the new branch grows to contain them all.
Finally, once all the commits are copied, git rebase
changes the originally-current branch name so that it points to the new tip-most commit on the new branch.
Note that nowhere in this process does git care whether the word origin
appears in <upstream>
. It simply resolves the <upstream>
argument to its SHA-1 and then runs with that.
Means that if you have a V2 and a V3 (Version 2 and Version 3 respectively), you can modify the V2 and with rebase
it will put the changes in a new version (V4) but merging with V3 (it doesn't matter that is a newer version of it) here is the link where you can see it more explained.
https://git-scm.com/docs/git-rebase
Note that if you are on branch X and you do git rebase -i master
, it changes branch X, not master, so you would have to push branch X.
Anyway, if origin/master
points to the same commit as master
(i.e. your master
branch is up to date), then it doesn't matter if you rebase onto one or the other. If they point to different commits, then you will be rebasing onto whatever commit the branch you choose points to.
When you use the rebase command you will want to push to origin (the remote host ie GitHub or Bitbucket) either way once it is rebased, but the origin in front of <branch>
means you are referring to the branch as it is remotely rather than what you have locally on your machine.