gitgithubgit-rebasegit-interactive-rebase

Is there any difference between git fixup and drop + reword while interactive rebasing?


I've started looking into interactive rebasing a little more and I've come across some issues. They are about the "fixup" option. I am interested in what is the difference between fixup and drop + reword option. For example, let's say we have:

pick 577dab2 add navbar
pick 432fda1 fix navbar bug

What is the difference between these two:

pick 577dab2 add navbar
fixup 432fda1 fix navbar bug

and

drop 577dab2 add navbar
reword 432fda1 fix navbar bug -> reword it to 'add navbar'

It would make a difference if the fixup option provided resolution of conflicts if there were any when "merging" (I know it's not real merging, but let's call it that) with the previous commit (in my example, if there is any conflicts between 577dab2 and 432fda1 commit). However, as far as I have noticed, the implementation is only "meld into", that is, everything that is within the fixup commit (432fda1) will only be "transferred" to the previous commit (577dab2) and the name of that previous commit (577dab2) will be taken. In other words, even if there is conflicts, they won't be resolved because everything was just "transferred" from one commit to another.

So from what I understand so far, fixup just allows the same thing to be done faster... Can anyone tell me what the real difference (if any)?

Someone asked this question over 8 years ago, but no one answered, at least not completely. Here's link.


Solution

  • Your misunderstanding is conceptual about how rebase works. Rebasing is basically just cherry-picking each of the changes contained in a range of commits (thus the word "pick" in an interactive rebase). Note your thought about reaching the original state of a commit isn't relevant when cherry-picking or rebasing.

    Given that, consider the differences:

    pick aaaaaaa Add file A
    pick bbbbbbb Add file B
    # RESULTING COMMITS: 2 commits with those titles
    # RESULTING STATE:   File A and File B both exist.
    
    pick aaaaaaa Add file A
    fixup bbbbbbb Add file B
    # RESULTING COMMITS: 1 commit with title "Add file A"
    # RESULTING STATE:   File A and File B both exist.
    
    drop aaaaaaa Add file A
    reword bbbbbbb Add file B
    # RESULTING COMMITS: 1 commit with default title "Add file B", but pops up editor
    #                      and allows you to change it
    # RESULTING STATE:   Only File B exists.
    

    The same concept applies for 2 commits editing a single file, except now we introduce the possibility of conflicts. Suppose we have a file called file1 which contains a single character 'x'. And now we have two commits that simply change that character:

    pick aaaaaaa Change file1 to 'a'
    pick bbbbbbb Change file1 to 'b'
    # RESULTING COMMITS: 2 commits with those titles
    # RESULTING STATE:   file1 is 'b'
    
    pick aaaaaaa Change file1 to 'a'
    fixup bbbbbbb Change file1 to 'b'
    # RESULTING COMMITS: 1 commit with title "Change file1 to 'a'"
    # RESULTING STATE:   file1 is 'b'
    
    drop aaaaaaa Change file1 to 'a'
    reword bbbbbbb Change file1 to 'b'
    # CONFLICT! This is because commit bbbbbbb only knows how to change
    #   from 'a' to 'b', but right now the starting point is 'x' instead of
    #   'a', so it pauses and asks for your help. Most likely you'd want to 
    #   take 'b' in this case, and then:
    #
    # RESULTING COMMITS: 1 commit with default title "Change file1 to 'b'",
    #                      but pops up editor and allows you to change it
    # RESULTING STATE:   file1 is 'b'