问题
I currently am on my master branch, and my stage is dirty. I don't want to commit and I already have too many stashes to stash my changes (or am I too lazy ?).
I would like to move fast foward some branches without switching to them (remember, my stage is dirty).
How could I fastfoward optim to mobile ? or optim to master (my current branch) ?
image: http://i.stack.imgur.com/WUPeq.png
回答1:
Note: a branch name is merely a pointer to a (single) commit. The thing we tend to think of as "the branch"—the whole chain of commits—is found by working from each commit backwards to its parent(s). The parents are recorded only in the commits themselves, not in any branch names. It may help to think of branch names as sticky-notes that are pasted on to some particular commit. I can't draw that in text so I draw it below as an arrow (<--) instead.
Translating your image to text, rotating it, making an assumption or two, and truncating a bit to fit nicely in this answer, you're showing:
o...
/
--o--M--o--o--o--o--o--o--o--o--o--o--o <-- mobile
/
---o <-- optim, origin/optim
(Here "newer" stuff is towards the right, instead of above, and the text of the various commit messages is omitted.)
A "fast forward" occurs when:1
- you are "on a branch", i.e.,
HEADis a symbolic reference to a branch name - you ask git to merge with another commit (by name or SHA1 ID; usually by branch-name)
- and, the "merge with" commit is "straight ahead" of where the branch is now, i.e., it's possible to simply slide the branch name along some set of "descendent" links to get there. (More precisely, the
HEADcommit is an ancestor of the "to-be-merged" commit.)
Since optim points to a commit whose single descendent is the merge commit M, and that commit has one descendent for each little o to the right, git can slide the branch name optim forward along that chain of commits.
Hence:
$ git checkout optim; git merge mobile
would slide the label up-and-right to M, then further right to where mobile points, giving:
o...
/
--o--M--o--o--o--o--o--o--o--o--o--o--o <-- mobile, optim
/
---o <-- origin/optim
If you want to do that "manually", without doing anything else and without even being "on" that branch, you can just tell git "please re-point the branch name optim to target the same commit as the name mobile:
$ git branch -f optim mobile
The -f (or --force) flag says to go ahead and change an existing label's target-commit, rather than erroring out.
This command does not check that the operation is a fast-forward. (Of course plain git merge only checks for that to decide whether to do a fast-forward merge, or a "real" merge. However, you can ask git merge to do --ff-only, i.e., error out if the operation is not a fast-forward.)
1Fetch and push also apply the same kind of "fast forward" notion, so this is "when" but not "only when".
回答2:
Use git push . mobile:optim (yes, that's a dot) to fast-forward optim to mobile.
来源:https://stackoverflow.com/questions/19712998/how-do-i-fast-foward-branches-without-switching-to-them