Search code examples
gitgit-rebasegit-pull

Difference between `git pull --rebase --autostash` and `git pull --ff-only`?


Following question Can “git pull” automatically stash and pop pending changes has solutions using both:

  • git pull --rebase --autostash

  • git pull --ff-only

I am little bit confused about which one should I use. Do they actually accomplish same result? Very similiar question is asked which does not has --autostash parameter along with the --rebase


Solution

  • Imagine a situation where the remote has changes you don't:

    remote | A - B - C - D - E
           |
    local  | A - B - C
    

    Here you can git pull --ff-only, because it's possible to fast-forward from C to E. Now imagine you've also made changes:

    remote | A - B - C - D - E
           |
    local  | A - B - C - F - G
    

    If you git pull --ff-only, it will be rejected, because you can't fast-forward from G to E; per the docs (emphasis mine):

    With --ff-only, resolve the merge as a fast-forward when possible. When not possible, refuse to merge and exit with a non-zero status.

    There are two ways to solve this, either:

    • creating a merge commit (the default if a fast-forward isn't possible, or can be forced with --no-ff); or
    • rebasing (--rebase).

    If you git pull --rebase, it will roll your local copy back to C, fast-forward to E, then replay F and G onto the new parent, leaving:

    remote | A - B - C - D - E
           |
    local  | A - B - C - D - E - F' - G'
    

    --autostash is a separate argument, per the docs:

    This means that you can run the operation on a dirty worktree.

    In both cases above I assumed a clean worktree (i.e. git status shows "nothing to commit, working tree clean" - you have no uncommitted local changes), for simplicity's sake, but sometimes you might want to pull new changes while you have local work in progress.