1

Recently I've been using git with a system that applies patches as commits (Phabricator & Arcanist, but I don't think thats important for this question).

I often end up in the situation where I have a patch applied in the form of a commit, but I would like to edit that commit. Of course I can always make edits and git commit --amend, but I'd also like to be able to do git diff, use meld . and other tools which assume edits are made on-top of the last commit.

Currently I do the following.


git diff HEAD~1 > temp.diff
git reset --hard HEAD~1
git apply temp.diff
rm temp.diff

Edit patch...

git commit -a

However this seems a bit clumsy, Is there some way to set the git repository to a another sha1, but keep the current working copy intact?

ideasman42
  • 42,413
  • 44
  • 197
  • 320

2 Answers2

3

You should be able to simplify your reset by using:

git reset @~

That will reset HEAD to the previous commit, and will reset the index, but not the working tree.
It used the default reset mode (like git reset --mixed)

A git diff should show you what that last patch was.
A git status should show you your last modified files, ready to be modified/added beck to the index and committed again.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Note: the use of `@` to refer to `HEAD` is new, older Git clients may need an explicit mention of `HEAD` in its place. –  Jun 20 '14 at 06:59
2

Depending on the exact behavior you want, git reset --soft and git reset --mixed will change the current commit to another commit (by rewriting the branch label if you're on a branch). Both of them do this sort of thing in terms of the commit graph:

[before `git reset`]

A - B - C - D   <-- HEAD=br1
      \
        E - F   <-- br2
          \
            G   <-- br3    [before `git reset`]

[after `git reset HEAD~1`]

            D   <-- only in reflog now
          /
A - B - C       <-- HEAD=br1
      \
        E - F   <-- br2
          \
            G   <-- br3

The difference is that git reset --soft leaves working directory and index intact, while git reset --mixed leaves working directory intact but changes the index to match the reset-to commit.

(For completeness, git reset --hard does what git reset --mixed does but also changes the work directory to match the reset-to commit. By saving the diff and then re-applying it with git apply you get the effect of git reset --mixed. If you plan to re-add everything, --soft probably makes more sense. Note that git commit --amend is essentially just git reset --soft && git commit in terms of commit-graph-and-index behavior.)

torek
  • 448,244
  • 59
  • 642
  • 775
  • Same idea as my answer, more details as usual. +1 – VonC Jun 20 '14 at 07:01
  • I considered briefly `reset --soft`, but decided to keep it simple at first. – VonC Jun 20 '14 at 07:01
  • 1
    I like `reset --soft` in http://stackoverflow.com/a/5203843/6309: "each time you are satisfied with what you end up with (in term of working tree and index), but you are not satisfied with all the commits that took you to get there: `git reset --soft` is the answer." – VonC Jun 20 '14 at 07:03