When will I see this message?
When you run git merge --ff-only <some/branch>
or git pull --ff-only <remote> <some/branch>
, and the branch or commit you are trying to merge is not based off your current branch—its history has somehow forked from yours.
git pull
can have defaults set in the configuration, so you can also see this if you ran a plain git pull origin <some/branch>
, and your config has pull.ff = only
.
To check your config: run git config pull.ff
or git config --show-origin pull.ff
(git merge
has a similar merge.ff
option)
How can I see what doesn't work?
To view the history of both your branch and the target branch, you can use:
git log --graph --oneline HEAD <some/branch>
If you didn't explicitly type a branch name (e.g: git merge --ff-only
or git pull --ff-only
), git
defaults to "the upstream branch of your active branch" -- it often is origin/mybranch
. A way to reference that branch from the command line is @{u}
:
git log --graph --oneline HEAD @{u}
# For Powershell users: @{...} is an operator, you will need to quote "@{u}"
git log --graph --oneline HEAD "@{u}"
You should see the divergence between your current branch and the target branch.
See also "More git log
options" below.
What can I do to fix this?
This depends on the result you want to reach, and what you see in the history above.
You may want to rebase your commits on top of target commit:
git rebase <some/branch>
# To rebase on top of your default upstream:
git rebase # The same as 'git rebase @{u}'
You may want to run an actual merge instead of only allowing fast forwards:
git merge <some/branch>
git merge # The same as 'git merge @{u}'
Or anything that suits your needs:
- cherry-pick some of your commits on top of the remote branch,
- use
git rebase -i
,
- merge the other way around...
How can I avoid this when I run git pull
?
If you have set --ff-only
as a default (e.g: if git config pull.ff
returns only
), you can override this default on a one off basis by explicitly providing a command line flag:
git pull --rebase # Rebase on top of fetched branch, rather than merge it.
git pull --ff # Run a normal merge
# (note: you *will* have a merge commit in your history)
If you want to change that default to some other value:
# Remove that default value, allow normal merges when pulling
git config --global --unset pull.ff
# Run `git pull --rebase` by default
# Note: you still need to run 'git config --global --unset pull.ff'
git config --global pull.rebase true
More git log
options
To see the differences between two branches in your terminal:
git log --oneline --graph a b
will show you the complete histories of a
and b
combined together.
If you want to see the history of a
and b
since they forked:
git log --oneline --graph --boundary a...b
# a...b (3 dots) : Means 'symmetric difference' in git log
# --boundary : Will show the commit that was at the fork point
# without this option, the two histories will be
# printed one below the other
If you want to hide side branches -- for example, if you want to view git log my/branch...master
, but you don't want to view the details of all pull requests that got merged in master
:
git log --oneline --graph --boundary --first-parent a...b
# --first-parent : On merge commits, only follow the first parent
Many graphical frontend to Git (Git Extensions, TortoiseGit, gitk, etc.) have ways to activate these options when you view your repositories history.
Look for the checkboxes in your GUI, and for fields where you may type a...b
or HEAD...@{u}
.
If you intend to use some of these commands on a regular basis, set an alias for them:
# Example: show HEAD vs @{upstream} log
git config --global alias.whatsup 'log --oneline --graph --boundary HEAD...@{u}'
# You can now run:
git whatsup