xbmono xbmono - 2 months ago 5x
Git Question

How to rebase individual files before merging in Git?

So this is a problem we have every now and then in a company with a large number of developers: There is a pull request for a feature branch to be merged in develop branch. While code review we notice that some files should not be merged in because the changes are mistakenly made against the old version of those files and now those files are not needed. There are other different scenarios that we need to exclude some files from being merged and the changes we want to be discarded or rebased with the one in the develop branch. It seems there is no simple way to do that, I tried to create a new branch and cherry pick from the feature branch but even that's not easy when the feature branch is too big.

Is there any simple way to reset individual files with the one in the develop and discard those changes?


There are basically two ways to solve that. Which one is the best depends on your workflow so I'll just explain both of them:

Adding more commit(s) reverting the changes

You could just add one or more commits on the top of your branch which undo all changes not to be merged. In this case you might want to start merging the changes from the develop branch into the feature branch to work with the most current version.

As you specifically asked for excluding complete files, you can reset a file to the develop version using this command:

git checkout develop -- path/to/file

This will put the file version from develop into your index. Review what will change using git diff --cached and if you want these changes you can commit them or otherwise adapt them as required.

This way of removing changes will keep the history of what happened in the feature branch. That can be helpful to understand why you didn't do what you initially planned if you document that decision in your later commit.

Rebasing the feature branch

You can also fix up your feature branch by changing its history. Attention: Changing the history of a branch is not a good idea if the branch is already shared with someone else. When the old and the new version of the branch are merged, git does not recognize that it was the same before and you will get a mix of both versions. If you do this you need to make sure the old version of the branch is discarded.

The analogy to merging develop from the first case would be to do (while your feature branch is checked out)

git rebase develop

This is the analogy to creating a new branch and cherry-picking all commits from the feature branch. If conflicts occur you will be prompted to solve them.

Afterwards you will probably need to edit some of your commits to remove changes you don't want in the feature branch anymore. One way to do this is interactive rebasing. If you do git rebase -i develop, you will get a list of all commits from your feature branch, prefixed with "pick". That means that this commit is used as it was before. You can change "pick" to "edit" for those commits you want to change. Git will then apply one commit after another and stop before applying those you want to edit. You can now adapt the changes for this commit, commit them (the original message will be provided) and continue rebasing with git rebase --continue.

If you now what to change in the beginning, you can also start off with git rebase -i develop, which will combine both steps in one.

There are many more ways to change your history. E.g. you might want to have a look at the option --fixup for git commit and --autosquash for git rebase, which allow you to add new commits which fix the older ones and the automatically unite them.