Remove Specific Files from Old Git Commit

ybbond

Yohanes Bandung Bondowoso

Posted on June 20, 2020

Remove Specific Files from Old Git Commit

tldr; Skip to solution »

Last week, I encountered a merge conflict while trying to sync my git working branch to latest remote master. Merge conflicts is not a serious problem to me, I am used to resolving conflicts. But the conflict that I encountered is from an auto generated typings file from Apollo Codegen1.

Apollo Codegen file is Flow or TypeScript typings for the schema and queries in project that uses GraphQL. The generated file often has >10k lines of code. Trying to resolve conflict in that file will make the text editor unresponsive (even with Vim!).

So I aborted the sync master (git rebase --abort), then attempt to remove the changes for the auto-generated codegen file using lazygit. Afterwards, I do sync remote master branch and the conflict don't happen. Last thing I do is regenerate the codegen file before posting a Pull Request.

How-Tos

Back to the post's main topic, to remove specific file using plain old shell command.

First, checkout to temporary branch with the afore mentioned commit as HEAD using the commit's hash:

git checkout <commit-hash>
Enter fullscreen mode Exit fullscreen mode

Then do a soft reset to uncommit with all files in staged status:

git reset --soft HEAD^
Enter fullscreen mode Exit fullscreen mode

Make the desired file(s) unstaged using reset command, and then commit with -c ORIG_HEAD flag to use the previous commit message. The --no-edit flag is optional.

git reset <path/to/file>

git commit -c ORIG_HEAD --no-edit
Enter fullscreen mode Exit fullscreen mode

Discard the changes of the file you want to remove from unstaged area:

git checkout -- .
Enter fullscreen mode Exit fullscreen mode

Last, rebase this temporary branch to your branch, from the commit of <commit-hash>.

git rebase --onto HEAD <commit-hash> <destination-branch-name>
Enter fullscreen mode Exit fullscreen mode

If you do this for already merged Pull Request, you need to push <remote> <branch> --force. Mind you, doing this will be inconvenient for other people working on same project.

Lazygit Way

As I mentioned above, I use lazygit. The process is more straight forward. For the following example, I accidentally committed build file, far before I .gitignored build/ folder. What I do is:

Navigate to desired commit

Navigate to desired commit

Press return key, and navigate to file to be removed

Press return key, and navigate to file to be removed

Press  raw `x` endraw  will prompt command list. Turns out d will discard the file

Press x will prompt command list. Turns out d will discard the file

After pressing  raw `d` endraw , the  raw `Index.js` endraw  file is now removed!

After pressing d, the Index.js file is now removed!

Do this way if you want to install lazygit before doing your intention.

lazygit way is easier. I also use tig as a TUI for git, but I don't know the command to do the steps wit tig.


  1. Here is Apollo Codegen Github page. As a frontend engineer, I consider codegen as breakthrough because I can easily type the endpoint's return value. 

💖 💪 🙅 🚩
ybbond
Yohanes Bandung Bondowoso

Posted on June 20, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related