Back to the future with Git’s diff and apply commands
Warning: This post is over a year old. I don't always update old posts with new information, so some of this information may be out of date.
This is one of those “there’s probably already a better way to do this” situations, but it worked.
I was having some issues this past weekend where, despite everything working fine locally, a server was showing a “500 Internal Server” after I pushed some changes to a site. In order to bring the site back online, I needed to revert the site files back to the previous version, but as part of a new commit.
git reset commands removed the interim commits which meant that I couldn’t push to the remote (force pushing, quite rightly, isn’t allowed for the production branch), and using
git revert was resulting in merge conflicts in
composer.lock that I’d rather have avoided if possible.
This is what
git log --oneline -n 4 was outputting:
14e40bc Change webflo/drupal-core-require-dev version fc058bb Add services.yml 60bcf33 Update composer.json and re-generate lock file 722210c More styling
722210c is the commit SHA that I needed to go back to.
My first solution was to use
git diff to create a single patch file of all of the changes from the current point back to the original commit. In this case, I’m using
head~3 (four commits before
head) as the original reference, I could have alternatively used a commit ID, tag or branch name.
git diff head head~3 > temp.patch git apply -v temp.patch
With the files are back in the former state, I can remove the patch, add the files as a new commit and push them to the remote.
rm temp.patch git add . git commit -m 'Back to the future' git push
Although the files are back in their previous, working state, as this is a new commit with a new commit SHA reference, there is no issue with the remote rejecting the commit or needing to attempt to force push.
The second solution is just a shorter, cleaner version of the first!
Rather than creating a patch file and applying it, the output from
git diff can be piped straight into
git diff head~3 head | git apply -v
This means that there’s only one command to run and no leftover patch file, and I can go ahead and add and commit the changes straight away.
About the Author
Oliver Davies is a Full Stack Web Developer and System Administrator based in the UK. He is a Senior Software Engineer and Technical Team Lead at Inviqa and a part-time freelancer specialising in Drupal, Symfony and Laravel development and Linux systems administration.