问题
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.,
HEAD
is 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
HEAD
commit 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