3

git reset --soft will keep your current changes, but move HEAD to another commit.

I am looking for an inverse of this operation, so that HEAD would remain stationary but state of all files would be set to the same as in commit CommitX.

I found a workaround:

git diff --no-prefix HEAD..CommitX | patch -p0

But I am wondering if there is a simple git command to do that.

Michael
  • 215
  • 1
  • 6
  • 2
    `git checkout` is the command you are looking for. However, you must use it in the mode where it does not check out (a branch) and instead simply extracts (files: all of them; if there are files that should go away when moving the work dir to commit X you must remove those; the easy way is to simply remove everything, then `git checkout X -- .` from the top level). – torek Sep 04 '16 at 12:00
  • Take a look at this question: [Undoing git reset](http://stackoverflow.com/questions/2510276/undoing-git-reset) – Andrii Abramov Sep 04 '16 at 12:08

2 Answers2

3

You can use git read-tree command to read particular tree into index. With -m -u options it will also update working directory.

git read-tree -m -u CommitX
user4003407
  • 21,204
  • 4
  • 50
  • 60
  • Thanks! This is exactly what I was looking for. – Michael Sep 04 '16 at 13:38
  • Note that with `-m`, it performs a *merge*, which is not the same as simply overwriting the index with the target commit's content. (You could first empty out the index though.) – torek Sep 05 '16 at 02:45
  • @torek Documentation says: "If only 1 tree is specified, *git read-tree* operates as if the user did not specify `-m`, except that if the original index has an entry for a given pathname, and the contents of the path match with the tree being read, the stat info from the index is used." So, you will not have any difference in index content with or without `-m`. – user4003407 Sep 05 '16 at 05:06
  • @PetSerAl: aha! I missed the "single tree merge" case. That's not really a merge at all, so `-m` is pretty misleading. (Incidentally, experimenting with `git read-tree` with and without `-m` and `-u` produces interesting results: `git read-tree -m -u` only works as desired if it is done initially, not if it is done again after a `read-tree` without `-u`.) – torek Sep 05 '16 at 05:59
  • @torek `-m -u` only checkout affected index entries, it keep unstaged changes otherwise. – user4003407 Sep 05 '16 at 17:08
0

An alternative to git read-tree -m -u is git read-tree --reset -u, which is now documented in Git 2.22 (Q2 2019), and can matter if "state of all files would be set to the same as in commit CommitX" includes merge commits.

See commit b5a0bd6 (01 Apr 2019) by Nguyễn Thái Ngọc Duy (pclouds).
(Merged by Junio C Hamano -- gitster -- in commit 87e20f8, 22 Apr 2019)

read-tree.txt: clarify --reset and worktree changes

The description of --reset stays true to the first implementation in 438195c (git-read-tree: add "--reset" flag, 2005-06-09, Git v0.99).
That is, --reset discards unmerged entries.
Or at least true to the commit message because I can't be sure about read-tree's behavior regarding local changes.

But in fcc387d (read-tree -m -u: do not overwrite or remove untracked working tree files., 2006-05-17, Git v1.4.0-rc1), it is clear that "-m -u" tries to keep local changes, while --reset is singled out and will keep overwriting worktree files.
It's not stated in the commit message, but it's obvious from the patch.

I went this far back not because I had a lot of free time, but because I did not trust my reading of unpack-trees.c code. So far I think the related changes in history agree with my understanding of the current code, that "--reset" loses local changes.

This behavior is not mentioned in git-read-tree.txt, even though old-timers probably can just guess it based on the "reset" name.
Update git-read-tree.txt about this.

Side note. There's another change regarding --reset that is not obviously about local changes, b018ff6 (unpack-trees: fix "read-tree -u --reset A B" with conflicted index, 2012-12-29, Git v1.8.5.2).
But I'm pretty sure this is about the first function of --reset, to discard unmerged entries correctly.

So the documentation now states:

`--reset`:

Same as -m, except that unmerged entries are discarded instead of failing.
When used with -u, updates leading to loss of working tree changes will not abort the operation.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250