git-checkout older revision of a file under a new name

Git

Git Problem Overview


I have the file "main.cpp" open in my editor.

I want to see the previous revision of "main.cpp" in the editor too.

The way I do it now is like this.

close "main.cpp" in the editor

prompt> mv main.cpp tmp
prompt> git checkout HEAD^ main.cpp
prompt> mv main.cpp old_main.cpp
prompt> mv tmp main.cpp
prompt>

open "main.cpp" and "old_main.cpp" in the editor

Can it be simplified, so I don't have to close "main.cpp" in the editor?

What I'm hoping for is a variant of git-checkout that can do this.


UPDATE: im using git on mac osx 10.5.7

prompt> git --version
git version 1.6.0.4
prompt> 

UPDATE2: Jakub Narębski answer is:

prompt> git show HEAD^:dir1/dir2/dir3/main.cpp > old_main.cpp
prompt>

UPDATE3: Karmi's answer, for a specific revision:

prompt> git show 4c274dd91dc:higgs/Higgs.xcodeproj/project.pbxproj > old_project.pbxproj
prompt> 

Git Solutions


Solution 1 - Git

You can use git show for that:

git show HEAD^:main.cpp > old_main.cpp

(Note that there is colon [:] character between HEAD^ and main.cpp.) The <revision>:<path> syntax is described in [git rev-parse][git-rev-parse] manpage, next to last point in the "Specifying revisions" section:

> <rev>:<path>, e.g. HEAD:README, :README, master:./README > > A suffix : followed by a path names the blob or tree at the given path in the tree-ish > object named by the part before the colon. :path (with an empty part before the colon) > is a special case of the syntax described next: content recorded in the index at the > given path. A path starting with ./ or ../ is relative to the current working directory. > The given path will be converted to be relative to the working tree’s root directory. > This is most useful to address a blob or tree from a commit or tree that has the same > tree structure as the working tree.

Note that <path> here is FULL path relative to the top directory of your project, i.e. the directory with .git/ directory. (Or, to be more exact, to "<revision>", which in general can be any <tree-ish>, i.e. something that represents tree.)

If you want to use path relative to the current directory, you need to use ./<path> syntax (or ../path to go up from current directory).

Edit 2015-01-15: added information about relative path syntax


You can get in most cases the same output using low-level (plumbing) git cat-file command:

git cat-file blob HEAD^:main.cpp > old_main.cpp

[git-rev-parse]: http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html "git-rev-parse(1) Manual Page"

Solution 2 - Git

Just to add to Jakub's answer: you don't even have to redirect the output to a file with >, if you are only interested in skimming the file contents in the terminal. You can just run $ git show 58a3db6:path/to/your/file.txt.

Solution 3 - Git

Singular use case

In order to get consistent checkout behavior including autocrlf etc., use a secondary folder (TEMP as example) and restore the file state from an older / different like this:

git --work-tree TEMP/ restore -s <commit> main.cpp
mv TEMP/main.cpp old_main.cpp

Note:

git show <commit>:main.cpp > old_main.cpp

.. will just produce a raw read from the repository.

Use a 2nd work tree - anonymous or linked

For more comfort working with alternative file states (without the need for renaming) use a secondary "anonymous" directory as a (long term) parallel work tree like this:

# one time setup
mkdir WD2
cd WD2
echo gitdir: WD1 > .git

# operate freely here with an alternative file set while the same branch is checked out in git
git restore -s <commit> main.cpp

(WD2 : path to secondary dir. WD1 : path to primary dir - Absolute or relative)

Note: Any kind of git project work (restore / add / commit / switch ..., build tasks) can be done with that alternative file set - as if suddenly the work tree files in WD1 would have been swapped. Hard links could be used for efficiently mirroring unchanged files in huge repos.

Similarly a "linked working tree" can be used via git-worktree (new since git v2.6.7). This causes somewhat more git overhead, but allows to checkout and work on a different branch (or detached head) simultaneously without using an extra repo.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionneoneyeView Question on Stackoverflow
Solution 1 - GitJakub NarębskiView Answer on Stackoverflow
Solution 2 - GitkarmiView Answer on Stackoverflow
Solution 3 - GitkxrView Answer on Stackoverflow