6

I'm aware of how git rebase works, and I've been using it in production for a while. It replays all of the commits of a branch onto another branch. It rewrites history of your current branch.

I've recently started playing around with git rebase --skip, although I was initially terrified of it. I realize it just skips that commit as if it never happened.

It seems to me that the resulting working directory would be the same in these two cases:

1) all of the commits are skipped except the most recent

2) all of the commits are replayed, such that the commits are resolved in favor of their branch.

Reminder: their is the branch that you are currently on when you rebase.
Other reminder: I'm specifically interested in the working directory. Is this the same?

Is it true that the working directory is the same result?

Lazy Badger
  • 94,711
  • 9
  • 78
  • 110
makansij
  • 9,303
  • 37
  • 105
  • 183

1 Answers1

6

In general, no. A replay of a commit is very similar to the cherry-pick operation. Not the state of the repository is applied, only the patch (=diff, changeset, ...) corresponding to that commit. If you skip commits, you omit the changeset, which may or may not result in conflicts. Either way, only skipping empty commits yields the same results in general.

However, if you perform an interactive rebase and squash all commits into one, the resulting work tree should be the same. Be sure to know about Undoing a git rebase if necessary. (Or better, perform all rebasing operations in an one-off branch, branched off the original "their" branch. Then, you can always double-check if the results have changed by comparing that rebased one-off branch with the "their" branch, and update the "their" branch only after everything is good.)

Community
  • 1
  • 1
krlmlr
  • 25,056
  • 14
  • 120
  • 217
  • "...only skipping empty commits yields the same results...". Yields the same results as which one? Replaying? Or skipping? – makansij Sep 09 '15 at 20:05
  • Thank you for your answer. I still can't think of a concrete example in which the two would result in different working directories. Yes, they are different processes - but since a `commit` is just a saved state of the repository, then I can't think of an example when these would be different? – makansij Sep 09 '15 at 20:30
  • 2
    It applies the *diffs* of the commits as a *patch* one at a time. If you skip one, you are not applying it, and the changes made there will not show up in the resulting working directory. The only case where the results would be the same is if the changes in the commit that was skipped were completely overwritten by a subsequent commit that was not skipped. – Daiku Sep 09 '15 at 20:37
  • And the suggestion to squash your commits before the rebase is spot-on. That makes the rebase much less painful if there are conflicts. – Daiku Sep 09 '15 at 20:47
  • Okay, thanks to both of you. So, I suppose an example might be if there were one upstream commit in which a new file was introduced, and the downstream commits did not modify this file at all. In case 1) this new file would not be introduced because that upstream commit was skipped. In case 2) this new file will exist in the working directory because the commit that introduced it was replayed. Again, a concrete example would really help me visualize this... – makansij Sep 09 '15 at 21:14
  • @Hunle: It's simple enough to create an example as you described, even locally -- you don't even need a remote, just two local branches. I'm having trouble understanding your question after the edit. Perhaps you can be a bit more specific why you care about the working directory (which is just the same as the Git tree on rebase, because rebase requires a clean status before it even starts). Perhaps an example of your application would help, too. – krlmlr Sep 09 '15 at 22:02
  • I care about the working directory because I only care about the final result. I know that the commit history will look different in 1) and 2). – makansij Sep 24 '15 at 02:09
  • And, @krlmlr, the application is that it is much easier to resolve in favor of `--their` (which is a one-liner) , rather than executing `git rebase --skip` all the way until the last commit (even if you're doing it interactively). – makansij Sep 24 '15 at 02:11
  • 1
    @Hunle: This is basically overwriting anything else that happened on the branch you rebase onto (i.e., everybody else's work, and your own unrelated work) with your newest patches, even if they don't apply anymore. I'm still not sure I understand your use case. What do you have in your Git repo -- plain text files? source code? There is no guarantee that the result will be even syntactically valid. What do you want to achieve finally? Are you looking for magic that resolves merge conflicts for you? I'm afraid this is just not possible. – krlmlr Sep 24 '15 at 04:41
  • @Hunle: I'm fine with the answer as it stands, please feel free to add your own answer or edit mine. – krlmlr Aug 07 '17 at 19:24