Drewsonian Drewsonian - 2 months ago 18
Git Question

Git rebase patches file in the wrong place

I am unsure whether this is the intended and known operation of git rebase or if I've found an issue. I have replicated it in a public repository using lorem ipsum. (https://github.com/drewclauson/git-rebase-example)

The issue occurs when I have two sections of code that are exactly the same for several lines (see lorem ipsum.txt). Ideally, the code would be refactored to keep it DRY, but I didn't know that the duplicate code in the same file existed.

branch1
has a commit that
master
does not have and vice versa, so I am rebasing
branch1
onto
master
.

branch1's
change is adding a line between lines 23 and 24. ("Test add a line of code")

master's
change is editing line 23. (insert "NEW TEXT" on line 23)

When I rebase
branch1
onto
master
, the change from
branch1's
commit gets patched in between lines 8-9 instead of between lines 24-25.

I dont' know much about git's operation, but I'm assuming that it has something to do with the context of the commit that should add the line between 24 and 25? Basically, it wants to patch based on the lines before and afterward, and since there is identical code earlier in the file, it just throws the patch there without considering line numbers? Or is there something I'm missing?

Thanks, I'm still a relative newbie to git, so it may be that I just don't understand something about it.

Answer

As you suspect, Git finds matching context and applies the change to it. Usually if rebase succeeds without conflicts everything is good, but sometimes not. Always verify the result and fixup as needed.

Ideally you would not have this duplication to trip Git up, but there are other ways to end up with broken commits after a "successful" rebase that are harder to avoid. For example, let's say we have a branch that adds a block of code making use of a variable x in some function foo(). Now imagine that someone decides x is not a descriptive name and renames it to foo_counter on master. If we rebase our branch onto master, it's quite possible the textual merge of our code will succeed even though the resulting commit will fail to compile (since we are referring to a variable that was never declared.) In this scenario we need to fixup the rebased commit to use foo_counter instead of x. Again, always verify the reslt of a rebase.

This hints at one of the disadvantages of rebasing when compared to merging that is often lost on newer Git users. Merging preserves the commits on the original branch so only the final merge commit needs to be verified. With a rebase, though, each of the rebased commits must be tested to avoid degrading the integrity of the repository. Often times a rebased branch will be fixed up with an additional commit made on top, leaving the intermediate commits in an untestable state. This can happen even if the final result looks alright. This may not seem important, but if you ever use Git's bisect you will appreciate having a testable history. Not that this cannot be achieved with rebasing, it just requires a bit more work.

Comments