Skip to main content

You are not logged in. Your edit will be placed in a queue until it is peer reviewed.

We welcome edits that make the post easier to understand and more valuable for readers. Because community members review edits, please try to make the post substantially better than how you found it, for example, by fixing grammar or adding additional resources and hyperlinks.

6
  • Everything works as you wrote, thank you very much, but I'm a little bit confused about git merge --ff-only feature~1 command, can you elaborate more on this, or send some useful sources to learn more?
    – pablocity
    Commented Jun 28, 2018 at 20:22
  • @pablocity: git merge is a tricky little command because—like too many other Git commands, in my opinion—it can do one of several different things. One of these is a true merge, in which Git creates a new commit that has two (or more but let's not go there) parents. The other is what Git calls, variously, a fast-forward or, especially when done via git merge, a fast-forward merge (kind of a misnomer as there is no actual merging occurring!). Fast-forward is actually a property of label movement. Note that when we use git branch -f or git reset, we move some branch name ... 1/
    – torek
    Commented Jun 28, 2018 at 21:52
  • ... from wherever it pointed before, to any commit we choose. The motion of that label (in this case, a branch name) can be a fast-forward or a non-fast-forward, and what distinguishes these is whether the new commit has the original commit as an ancestor, i.e., whether, by starting at the new commit and working back through the commit graph, we can reach the previous commit. If we can reach the previous commit, this change was a fast-forward. 2/
    – torek
    Commented Jun 28, 2018 at 21:54
  • Both git push and git fetch favor fast-forward operations: they will happily adjust branch names, and for fetch, remote-tracking names, that result in fast-forwards. They object to non-fast-forward updates, requiring --force or equivalent. This guarantees that the change, whatever it is, preserves all the existing commits and merely adds some more (or in the degenerate case, changes nothing at all—the label already points to the new commit). Anyway, that's great for fetch and push, but what about merge? 3/
    – torek
    Commented Jun 28, 2018 at 21:57
  • When you do any git merge <commit-hash-or-name> operation, the merge code inspects the current commit (using HEAD to find its hash ID) and the target commit (whatever you named on the command line), and does one of these ancestor tests. If the current commit is an ancestor of the target commit, the merge operation is deemed unnecessary: a fast-forward will do. This is where --ff-only and --no-ff enter the picture: the former requires it and the latter forbids it, forcing Git to make a merge commit instead. 4/
    – torek
    Commented Jun 28, 2018 at 21:58