The --no-ff flag prevents git merge from executing a "fast-forward" if it detects that your current HEAD is an ancestor of the commit you're trying to merge. A fast-forward is when, instead of constructing a merge commit, git just moves your branch pointer to point at the incoming commit. This commonly occurs when doing a git pull without any local changes.

However, occasionally you want to prevent this behavior from happening, typically because you want to maintain a specific branch topology (e.g. you're merging in a topic branch and you want to ensure it looks that way when reading history). In order to do that, you can pass the --no-ff flag and git merge will always construct a merge instead of fast-forwarding.

Similarly, if you want to execute a git pull or use git merge in order to explicitly fast-forward, and you want to bail out if it can't fast-forward, then you can use the --ff-only flag. This way you can regularly do something like git pull --ff-only without thinking, and then if it errors out you can go back and decide if you want to merge or rebase.