Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I edit a previous git commit? [duplicate]

Tags:

git

I just realized that I left out a file that I was supposed to add to a commit like 5 commits back. In the commit message I said that the file was included, and I don't feel like doing a new commit with the text "Oops forgot to add this file in commit #XXXXX"

What's the best way to edit a previous commit so I can add the file?

like image 901
Hubro Avatar asked Jan 26 '12 19:01

Hubro


People also ask

How do I overwrite a previous commit?

If you've already created a fresh commit, you'll want to use git rebase -i to squash your commit on top of the old one. After you've made this change locally, and verified your commit looks the way you want it to, you'll have to git push --force to overwrite history on the Github remote.


2 Answers

Commit your fix, then use git rebase --interactive to reorder your commits and squash the two commits together. See the git book for details.

Note that doing this is bad idea if those commits have been pushed somewehere already, since you will change the repository history.

An example session could look like this:

% git init
Initialized empty Git repository in /home/user/repo/.git/
% echo "A line" > a.txt
% echo "A line" > b.txt
% git add a.txt b.txt
% git commit -m "Initial commit"
[master (root-commit) c6329d0] Initial commit
 2 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
 create mode 100644 b.txt

Your incomplete commit:

% echo "Another line" >> a.txt
% git add a.txt
% git commit -m "Important changes"
[master 0d28cfa] Important changes
 1 files changed, 1 insertions(+), 0 deletions(-)

Some other commit:

% echo "Yet another line" >> b.txt
% git add b.txt
% git commit -m "Other changes"
[master 96a092d] Other changes
 1 files changed, 1 insertions(+), 0 deletions(-)

Notice that you've forgotten somthing:

% echo "Important line forgotten previously" >> a.txt
% git add a.txt
% git commit -m "Oops"
[master 9dce889] Oops
 1 files changed, 1 insertions(+), 0 deletions(-)

Fix the history with git rebase -i:

% git rebase -i HEAD~3

You will be put into your editor of choice with contents similar to the following:

pick 0d28cfa Important changes
pick 96a092d Other changes
pick 9dce889 Oops

Change it so that the "oops" commit is moved one line above and change pick to squash (or just s) to combine it with the preceding commit:

pick 0d28cfa Important changes
s 9dce889 Oops
pick 96a092d Other changes

Then save the file and exit the edit. This will pop up another editor, where you can edit the commit message for the combined commit. It will look like this:

# This is a combination of 2 commits.
# The first commit's message is:

Important changes

# This is the 2nd commit message:

Oops

Change it as you feel is appropriate, then save and exit.

Finally, check that the new commit indeed is a combination of the two commits:

% git log -p HEAD~2..HEAD~1
commit 7a4c496956eb269c551bbf027db8b0f2320b65e4
Author: User Name <[email protected]>
Date:   Fri Feb 3 22:57:31 2012 +0100

    Important changes

diff --git a/a.txt b/a.txt
index 8d7158c..54df739 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,3 @@
 A line
+Another line
+Important line forgotten previously
like image 76
Mika Fischer Avatar answered Sep 18 '22 23:09

Mika Fischer


You can use the git commit --fixup <hash> to make a specially labelled commit that is intended to be merged with a previous commit whose hash is <hash>. This is ideal for adding missing files, or fixing typos etc.

Once you have the fixup commit, you need to use git rebase --interactive --autosquash <starting-point> to actually merge the fixup commit into the <hash> commit. The <starting-point> of the rebase should be some point in the history prior to the <hash> commit (you can just use <hash>^ for simplicity).

The usual caveats to history rewriting apply, if you have already published your branch somewhere that other users have pulled from, it will generally cause a lot of confusion and merging problems if you re-push with rewritten history. In these cases it is just simpler to push the correction as a new commit.

Note: git config --global rebase.autosquash true will turn on auto squashing by default, meaning you don't need to pass the --autosquash option to the rebase interactive command anymore. This is a good default to have.

A good walkthough of autosquashing can be found here: https://thoughtbot.com/blog/autosquashing-git-commits

like image 26
tul Avatar answered Sep 22 '22 23:09

tul