Robert Pounder
Robert Pounder

Reputation: 1511

Git checkout a revision without deleting unaffected files

I want to revert to a previous revision without deleting files, a visual representation of this would be:

3 files;

myfile
mysecondfile
mythirdfile

Now this is currently origin/master and my working copy.

What I want to do is revert to a previous revision, lets say DEADBEEF,

DEADBEEF revision only has one file;

myfile

What I want to do is overwrite my local myfile with the previous revision without deleting mysecondfile or mythirdfile.

Upvotes: 0

Views: 544

Answers (4)

VonC
VonC

Reputation: 1323943

To create a new commit with the content of an old commit (and your current files), try a combination of git read-tree, git checkout-index and git update-index:

git read-tree DEADBEEF 
git checkout-index -f -a
git update-index -q --refresh

Then commit.


Meaning: no need to use shell trick with xargs: git has the tools you need.

  • git read-tree DEADBEEF will restore the index from that old commit (which will make all other files "untracked" or "modified", since they were not part of that old commit DEADBEEF)
  • git checkout-index -f -a will force the working tree to reflect that index (again, without modifying the files which were not part of the index)
  • git update-index -q --refresh will make sure index and working tree are in sync.

Finally add and commit: you will get all your other files plus the content of the old commit.

Upvotes: 3

AnimiVulpis
AnimiVulpis

Reputation: 2726

Solution first

If you have the possibility to use the xargs command line command that is an easy task.

$ git ls-tree --name-only -r <tree-ish> . | xargs git checkout <tree-ish> --

Breakdown of commands used

  • git ls-tree will list the content of a tree object
    This means it will show all the files that were present in the repository at a certain commit
    • --name-only will restrict the output to the (relative, use --full-name for absolute paths) path of the files
    • -r will show all files recursively
  • | will pipe the output of one command to the next
  • xargs is used here to give the result of ls-tree as arguments to git checkout
  • git checkout <tree-ish> -- will (in this form) checkout files from the given tree-ish without changing branches

Bonus: Show what you changed in those files

To view the changes that you did since <tree-ish> use:

$ git diff --staged -R

If the command is used without -R you would see the changes as if you changed everything to the old state.

Upvotes: 7

jthill
jthill

Reputation: 60255

For the situation you've given there, the command is

git checkout deadbeef -- .

which resets every file in commit deadbeef to its contents as of that commit.

Upvotes: 2

Sergei Voitovich
Sergei Voitovich

Reputation: 2952

If mr_sudaca's answer doesn't satisfy your desire I'm afraid there's no such possibility in git.

If you want your master HEAD to be pointed to myfile previous revision and keep mysecondfile and mythirdfile current state - just make it the git way, clear and easy:

  1. Save mysecondfile and mythirdfile somewhere.
  2. Run git revert [you latest commit sha-1] (sha-1 could be found by git log)
  3. Copy mysecondfile and mythirdfile back then make a new commit.

Upvotes: -1

Related Questions