Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to edit the last git commit as a patch file?

Tags:

git

Sometimes it is useful to modify a commit by editing a patch file rather than by changing files directly, adding them to the working set and then amending a commit.

To make this easy, it would be useful to have a command in git that opens the most recent commit in $EDITOR as a patch file, in the same way that issuing git commit --amend (without any changes staged) immediately allows editing of the commit message in an editor.

Is this possible in git

  1. as a single command
  2. without losing the commit message?
like image 443
wodow Avatar asked Aug 06 '19 11:08

wodow


People also ask

How do I make a patch for the last commit?

Click on latest commit. Add . patch at the end of this url . So the modified url looks like: https://github.com/xyz/lmn-ms/tree/branch_name.patch.

How do I amend a last second commit?

To change the most recent commit message, use the git commit --amend command. To change older or multiple commit messages, use git rebase -i HEAD~N . Don't amend pushed commits as it may potentially cause a lot of problems to your colleagues.

How do I format a patch in git?

The first rule takes precedence in the case of a single <commit>. To apply the second rule, i.e., format everything since the beginning of history up until <commit>, use the --root option: git format-patch --root <commit> . If you want to format only <commit> itself, you can do this with git format-patch -1 <commit> .


1 Answers

I'm not sure if it is possible in a single command, but almost:

git reset -N HEAD~
git add --edit
git commit --reuse-message=ORIG_HEAD

some explanations:

  • git reset -N HEAD~ : destroy last commit but keep the changes
  • git add --edit allows you to edit your changes in patch format
  • git commit --reuse-message=ORIG_HEAD : commit your staged changes with the commit message from ORIG_HEAD which is the pointer to the commit you made before git reset.

NOTE: since only git add --edit needs for interaction, you could even just chain the commands on one line and create a bash or git alias for it if desired:

git reset -N HEAD~ && git add --edit && git commit --reuse-message=ORIG_HEAD

NOTE2 if you edit your commit, some changes will remain in your git repository after this command. You must choose to throw them all away (git checkout -- :/) or commit them or...

If you don't do anything with these changes; then calling the above commands twice will always show you the changes from your very first commit:

git commit -am "very first commit"
git reset -N HEAD~
git add --edit # edit very first commit as patch
git commit --reuse-message=ORIG_HEAD
# you now have some unstaged changes lying around.
git reset HEAD~ # undo second commit
# the unstaged changes that are lying around now 
# are a combination of second commit and the unstaged changes
# that were still lying around.
# That combination = content of very first commit
git add --edit # edit that combination
git commit --reuse-message=ORIG_HEAD

If you would like a full command that you can continue applying; you could include the throwing away of changes:

git reset -N HEAD~ && git add --edit && git commit --reuse-message=ORIG_HEAD && git checkout -- :/

Note that this is dangerous because you might be throwing away changes...


full-blown script

you might save this script as /usr/bin/git-edit-last-commit, then you can run it as git edit-last-commit:

#!/bin/bash
set -e # exit on first error
if ! git diff-files --quiet
then
    echo "Your git repository is not clean: you have unstaged changes."
    exit 1
fi
if ! git diff-index --quiet --cached HEAD --
then
    echo "Your git repository is not clean: you have staged changes."
    exit 1
fi
git reset -N HEAD~
git add --edit
git commit --reuse-message=ORIG_HEAD
# supposing that this edit is really what you wanted, we can throw away leftovers
# if work was lost, in can be recovered using git reflog
git checkout -- :/
like image 178
Chris Maes Avatar answered Sep 22 '22 01:09

Chris Maes