I want to restore a few lines from a file recorded in an older commit. I can see those lines by running
git log -p
As a last resort, I'm ready to simply copy those lines from the output of that log, but that would hurt my purist's heart and seems rather unprofessional.
I do not want to simply run git checkout <file>
because that would discard local changes made to <file>
since the commit in question. Instead, I would like to merge changes from that commit into <file>
in the working tree using only pure Git commands.
How can I do that?
Use interactive checkout
The following git-checkout
syntax,
git checkout --patch <tree-ish> -- <paths>
or, equivalently,
git checkout -p <tree-ish> -- <paths>
allows you to interactively check out hunks from one or more files, listed in <paths>
, as recorded in <tree-ish>
(most commonly, a commit).
See the git-checkout
man page for more details.
Example
To fix ideas, here is a toy example (irrelevant stdout is omitted):
# set things up
$ mkdir test
$ cd test
$ git init
# create some content and commit
$ printf "Hello, world.\n" > README.md
$ printf "foo\nbar\nbaz\n" > test.txt
$ git add .
$ git commit -m "initial commit"
# modify the working tree
$ printf "another line\n" >> README.md
$ printf "foo\nfoo\n" > test.txt
# now restore stuff from test.txt as recorded in master's tip
$ git checkout -p master -- test.txt
diff --git b/test.txt a/test.txt
index 0d55bed..86e041d 100644
--- b/test.txt
+++ a/test.txt
@@ -1,2 +1,3 @@
foo
-foo
+bar
+baz
Apply this hunk to index and worktree [y,n,q,a,d,/,e,?]? y
error: patch failed: test.txt:1
error: test.txt: patch does not apply
The selected hunks do not apply to the index!
Apply them to the worktree anyway? y
# Sanity check: inspect the working tree
# (the hunk "bar\nbaz" from test.txt was restored, as desired)
$ cat test.txt
foo
bar
baz
# (README.md, on the other hand, was not affected, as desired)
$ cat README.md
Hello, world.
another line
If in the older commit you only changed this file, and you want to undo all those changes,
then simply do:
git revert SHA
If there were more than one files, here's a pure git
(and not great) solution:
git revert SHA --no-commit
git reset
git add path/to/file
git checkout .
git commit
Or a git
+ patch
solution (also not great):
git diff -p SHA path/to/file > patch
patch -R < patch
git commit .