Imagine you want to submit a huge merge request (gitlab terminology), that has many changes from a bunch of commits. You realize that you don’t want to see some changes, but these changes are not in separate commits, so they can’t be easily reverted. There are a lot of small changes. You don’t want to type their reverse, or copy-paste for minutes. You want to keep the commits, not squash them together in the end. What would you do?

I did not want to spend time to find the perfect solution, so I came up with a quick one.

What I really wanted is to see all changes in one commit, that I saw in my merge request, and select the code I wanted to get rid of, then apply these changes to my original branch.

In order to achieve that, I got the latest master, created a sandbox branch, squashed my target branch inside it, selected what code I wanted to get rid of, reverted that commit, and cherry picked it to my target branch.

SANDBOX_BRANCH=sandbox
TARGET_BRANCH=target

# 1. Get a clear sandbox with recent master
git checkout master
git pull
git checkout -b $SANDBOX_BRANCH

## 2. Get all changes as one commit
git merge $TARGET_BRANCH --squash
# ... select only the unnecessary code,
# ...   that you want to revert
git add .
git commit -m "Unnecessary code"
git revert HEAD
HASH=`git rev-parse --short HEAD`

## 3. Apply the inverse changes, cleanup
git checkout $TARGET_BRANCH
git cherry-pick $HASH
git commit --amend -v # rename commit
git branch -D $SANDBOX_BRANCH

Enjoy :)

P.S: Let me know if you have a better idea.