1

I am trying to figure out the easiest way to switch back and forth between version of code to test while making changes. When I'm in the middle of something and want to test out something else I'll use git stash but that seems like overkill in this situation as it can't be done on individual files.

What I tried to do was git add {file} to temporarily store changes and then git checkout {file} to get back to the previous state. The intention being to have staging as a temporary holding area for a file and then pull the staged file back into my working directory. I was surprised though that after staging a file the checkout had no effect on the file in the working directory. Is there a series of command options that would allow this work flow to function as I want it to?

Update 1:

Based on docs it appears this would work if there was a way for step 2 to not overwrite the index

  1. git add {file}
  2. git checkout HEAD {file}
  3. git checkout {file}

Update 2:

After being inspired by ElpieKay's post to look at writing output of a command to file I found another answer that overcomes the limitation of step 2 above. With git show HEAD:{file} > {file} I can now overwrite the working directory version of the file without overwriting index. Then calling checkout pulls the index version into the working directory. Combined with git checkout-index I get this...

  1. git add {file}
  2. git show HEAD:{file} > {file}
  3. git checkout-index -f
Community
  • 1
  • 1
Dan Roberts
  • 4,664
  • 3
  • 34
  • 43
  • Possible duplicate of [Stash only one file out of multiple files that have changed with Git?](http://stackoverflow.com/questions/3040833/stash-only-one-file-out-of-multiple-files-that-have-changed-with-git) – dnit13 Oct 14 '16 at 14:00
  • @dnit13 thanks for pointing out that post. I am digesting it now but on first look it does not appear to do what I need and could be very error prone. – Dan Roberts Oct 14 '16 at 14:08
  • Would working on a branch and navigating back and forth through parent commits be an option? You can always pick out a copy of a file from another branch. – Thorbjørn Ravn Andersen Oct 14 '16 at 14:14
  • I never had a good reason for doing something very mercurial like as having two copies of the repo… might this be a good reason for it? – Dacav Oct 14 '16 at 14:40
  • 1
    @Dacav: this is a reason to use the newish `git worktree` (although that forbids you from having two work-trees on the same branch, so you need to detach HEAD in one). – torek Oct 14 '16 at 22:55
  • 1
    @DanRoberts: note that `git show HEAD:path` does not run the file through any filters (smudge filters and CRLF manipulations). Sometimes that's a plus though! :-) – torek Oct 14 '16 at 22:57
  • @torek thanks for sharing. – Dacav Oct 17 '16 at 07:23

1 Answers1

0

You could simply use git commit if git stash is not good enough.

First let's make a tag to track the tip of the current branch.

    git tag start

After making the changes to some files,

    git add .
    git commit -m 'version 1'
    git tag v1
    #do the test

Make some other changes,

    git reset start --hard
    git add .
    git commit -m 'version 2'
    git tag v2

Supposing you are interested in different versions of file-a, use git checkout v1 -- file-a or git checkout v2 -- file-a or git checkout start -- file-a to switch file-a in the work tree. In the end, git tag -d start v1 v2 to remove the tags. And before that, run git reset start --hard if necessary. Branches can also work instead of tags.

To manipulate blobs directly is another approach.

    #make some changes to file-a
    #modify, modify, modify
    #create the blob of this file-a and make a tag for it.
    git tag v1 $(git hash-object -w file-a)

    #restore file-a to HEAD's version
    git checkout -- file-a

    #make some other changes to file-a
    #oh, oh, ah, ah
    #create the blob of this file-a and make another tag for it.
    git tag v2 $(git hash-object -w file-a)

    #now we want version1's file-a
    git cat-file -p v1 > file-a

    #now we want version2's file-a
    git cat-file -p v2 > file-a

After all is done, run git tag -d v1 v2. As to the temp blobs, just leave them alone if you don't need them any more and they won't bother you.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53
  • I added an update mentioning that the only piece of the puzzle missing appears to be the ability to checkout to working directory without overwriting staging area. I think the cat-file command may make this possible. – Dan Roberts Oct 14 '16 at 14:40
  • actually another question's answer may be it `git show branch:file > exported_file` – Dan Roberts Oct 14 '16 at 14:42
  • 1
    @DanRoberts `git show ` is equivalent to `git cat-file -p `. It can be done via different commands. – ElpieKay Oct 14 '16 at 14:49
  • ah ok, i wasn't clear from your code as -p v1 > file-a didn't mention file-a on the left side but that makes sense – Dan Roberts Oct 14 '16 at 14:51
  • 1
    @DanRoberts `v1` is a tag that points to one of the blobs of `file-a`. This blob is created by `git hash-object -w file-a`. – ElpieKay Oct 14 '16 at 14:54