118

I'm trying to script rebasing and my script will take different paths depending on if the rebase results in any conflicts.

Is there a way to determine if a rebase would result in conflicts before executing the rebase?

5
  • What is the exact form of the git rebase command you're using? Are you using any optional flags? And what scripting language are you using? Shell?
    – jub0bs
    Commented Apr 8, 2015 at 15:13
  • 3
    If you run git rebase and hit a merge conflict, the process will stop and exit with a nonzero status. You could check the exit status of the rebase operation, and, if it is nonzero, run git rebase --abort to cancel the operation.
    – jub0bs
    Commented Apr 8, 2015 at 15:15
  • 1
    Did you find a way of doing this?
    – crmpicco
    Commented Jul 8, 2015 at 14:07
  • 1
    @crmpicco I basically did what Jubobs suggested by going ahead with the rebase, checking for conflict, and aborting if needed. I wish there was a more elegant way however... Commented Jul 9, 2015 at 15:35
  • 2
    For messy rebases, I often create a new branch and do a trial run there first. If everything goes smoothly, the the trial run becomes the rebase, otherwise just switch back to the original branch.
    – jordanpg
    Commented May 30, 2017 at 14:58

6 Answers 6

84

At the time of writing this (Git v2.6.1 v2.10.0), the git rebase command offers no --dry-run option. There is no way of knowing, before actually attempting a rebase, whether or not you're going to run into conflicts.

However, if you run git rebase and hit a conflict, the process will stop and exit with a nonzero status. What you could do is check the exit status of the rebase operation, and, if it is nonzero, run git rebase --abort to cancel the rebase:

git rebase ... || git rebase --abort

And if the rebase is successful but you realise that you want to undo it, you can run

git reset --hard @{1}
3
  • 3
    @bluenote10 Or if you know that you will want to discard the rebase result no matter what, you can just start with a detached head: git checkout --detach foo. Commented Nov 16, 2018 at 0:50
  • 3
    You can also use git reset --hard ORIG_HEAD to move the branch back to where it was before the rebase. Commented Jan 23, 2020 at 14:48
  • 2
    Note that sometimes, ORIG_HEAD will not point to where the branch tip was before the rebase. This can happen if you use ` git reset` during the rebase, for example to split a commit (as of Git 2.39) (see the bug report). A safer alternative is ` git reset --hard @{1}`
    – philb
    Commented Jan 5, 2023 at 17:14
52

If you just want to see if the rebase would be successful but then you want to "roll back," you can alway reposition the branch tip back to the original commit. Just tag or make a note of the original SHA.

Or perhaps easier, create a new temporary branch in which to "stage" the rebase:

git checkout your-branch
git checkout -b tmp
git rebase other-branch

If it was successful but you want to "roll back," your-branch is untouched. Just git branch -D tmp and you're back to where you started from.

If there were conflicts and you did some work to resolve them and you now you want to keep the rebase, just reposition your-branch tip to tmp (and then git branch -D tmp).

1
  • 15
    A single command in place of the first two: git checkout -b tmp your-branch
    – ruvim
    Commented Jun 13, 2018 at 7:22
9

I suspect that git rebase ... --dry-run is not possible, for the following reason.

When you're doing a git rebase, git will rollback to the starting point, then incrementally apply patches for each commit to bring the branch up to date. If it hits a conflict, it will stop & wait for you to resolve the conflict before continuing. The path that the rebase takes after that conflict depends upon how you resolve the conflict - if you resolve it a certain way, that might introduce (or eliminate) later conflicts.

Thus, git rebase ... --dry-run would only be able to give you the first conflict - reports of later conflicts will depend upon how that first conflict is resolved.

The only way I can think of doing this would be via git diff between the current position and the last commit in the branch you're rebasing to. But that won't really give you what you're looking for - you really just need a list of conflicting changes between the two points. There might be a way to do it with git diff, but it's not a normal patch.

6

Building on @joneit's solution:

Create a new temp branch from your-branch and try to rebase that temp branch onto the new-base:

git checkout -b temp <your-branch> && git rebase <new-base>

e.g. to test if branch feature1 can be rebase'd onto master:

git checkout -b temp feature1 && git rebase master
5

You still can do git rebase, play with it as you want, than recover all the changes from before. Assuming you have done your rebase of some branch into the master, and you don't like it:

  1. git reflog -20 - gives you last 20 positions of your HEAD with a little description
  2. git checkout <the_branch_name> - places your HEAD on the branch
  3. git reset --hard <old_sha1_found_in_reflog> - places your HEAD and branch on the old ref, this way you can recover old branch.

There are some mechanics to understand here:

  1. You NEVER delete anything in git, not with commands, anyway. Its the garbage collector that comes through and deletes unreferenced branches (default 3 months). So your branch, from before the rebase, still exists.
  2. Same goes for the on same branch rebase, its just a new tree rewritten next to the old one.
  3. All the history of rebase and your other on HEAD manipulations is written in the reflog
  4. You can use @{N} annotations from reflog

So, nothing is lost after the rebase, you just have to know how to find and recover it.

For example you can place yourself a tag before the rebase than revert to it or delete it. it evades you all the SHA1 research step.

-1
git checkout ${BRANCH-HEAD}~0 && git rebase ... 

But --dry-run was better

2
  • 2
    Is this a new answer (in which case how does it compare to the existing ones?), or is this just a warning/comment to use --dry-run before running the real command?
    – mozway
    Commented Sep 15, 2023 at 7:17
  • Do you mean "was better in the past, pity that it was removed" or "would be better"? Because the other answers seem to imply that there never was a dry-run. Also, please explain the first part, that looks like a code-only solution.
    – Yunnosch
    Commented Sep 15, 2023 at 8:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.