1

I'm attempting to rebase a local development branch onto the latest version of master in order to incorporate the newest changes. However, this development branch is for cleanup work, so its commit history looks something like:

  • Normalize YAML whitespace
  • Standardize on double quotes for YAML string literals
  • Standardize docker-compose file organization & standard keys
  • Fix common typo of 'fu' where we mean 'foo'

This means I cannot trust Git's automatic merge conflict resolution system; even if none of the changes from master overlap with any of the changes from a given commit, the new code might nonetheless contain instances of the error which that commit is supposed to fix, e.g. adding a new block of YAML which doesn't use double-quoted string literals, or adding a new Docker service to a compose file which is lacking the standard keys.

What I'd like to do is run the rebase, but tell Git not to do any automatic merge resolution at all - that is, any file which has been modified in master should be marked as a merge conflict, even if none of the new code overlaps with my edits at all. That way, I can review each bit of added or edited code and manually apply the appropriate fixes. Is there any way to do this?

macdjord
  • 517
  • 2
  • 4
  • 13

2 Answers2

4

I don't think Git has a way to force a merge conflict in such a situation; it's not a generally useful feature, and I don't believe Git considers the history of the branch onto which you're rebasing when doing a rebase.

What you can do instead is do an interactive rebase with git rebase -i. If your changes can be applied automatically using a script, then you can use the -x option to run that script, add your changes, and then run git commit --amend --no-edit.

If this isn't scriptable, you can instead run a normal interactive rebase and then change every pick directive to edit, which will let you edit the commit as you see fit. You can use git diff --name-only HEAD^ to see the changed files so you only need to work on them. Git will tell you how to amend each commit and proceed once you're happy.

bk2204
  • 64,793
  • 6
  • 84
  • 100
2

To ellaborate on @bk2204's answer :

using git rebase -i instead of git rebase allows you to do several things :

  • you can change all pick actions in the sequencer script to edit :

    pick eacf32 commit 1         edit eacf32 commit 1
    pick cc561e commit 2     ->  edit cc561e commit 2
    ...                          ...
    

    that way git will stop after each commit, you can inspect the content, update and git commit --amend as needed

  • if the checking and updating can be scripted, you can add exec actions between commits :

    pick eacf32 commit 1
    exec normalize.sh
    pick cc561e commit 2
    exec normalize.sh
    ...
    

    the script will run on each "exec" step ; if any file on disk is changed, the rebase will stop and display an "error" message :

    error: cannot rebase: You have unstaged changes.
    warning: execution succeeded: normalize.sh
    but left changes to the index and/or the working tree
    Commit or stash your changes, and then run
    
       git rebase --continue
    

    which is actually a way of telling you "please inspect the content, edit it if needed, and commit the result"

  • you can have git insert every exec normalize.sh line for you using the -x option :

    git rebase -i -x normalize.sh
    
LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • Scripting is not practical; these changes were performed manually. Using the `edit` action is close to what I want, However, it leaves the repo in the state where the commit I'm editing is already committed, which means I'm left manually checking to find where things changed. Is there any way to make it stop in the state where the changes have been added to the commit but the commit has not been performed, instead? – macdjord Dec 01 '20 at 18:37
  • 1
    You can view the list of files modified by the most recent commit : `git show --name-status HEAD`. You can also use `reset --soft`, to have "what was committed" placed in the index : `git reset --soft HEAD^`. If the reset option is what you want : `git rebase -i -x 'git reset --soft HEAD^'` – LeGEC Dec 01 '20 at 19:13
  • One extra piece of advice : do check what could be automated. It looks like you are trying to perform a systematic operation manually, which is a known procedure to regularly have to fix what slipped in inadvertently. – LeGEC Dec 01 '20 at 19:16
  • Some of this could theoretically be automated; some of it cannot be because it requires human intervention. But it's not worth the effort; this is a one-time cleanup operation. – macdjord Dec 08 '20 at 21:20