# Extracting a file

8 messages from 2021-07-22 to 2021-07-23. Participants: Angelo Borsotti, Ævar Arnfjörð Bjarmason, Jeff King, Junio C Hamano, Felipe Contreras.
Thread: https://gitlist.dev/t/56143

## Angelo Borsotti, 2021-07-22 08:48

Subject: Extracting a file
Message-ID: <CAB9Jk9AafnUQr6q8t=b4Dh0PZHUA=fKJmtXxxObuGpF_w-_2wQ@mail.gmail.com>
URL: https://gitlist.dev/e/CAB9Jk9AafnUQr6q8t%3Db4Dh0PZHUA%3DfKJmtXxxObuGpF_w-_2wQ%40mail.gmail.com

```
Hi,

sometimes there is a need to extract a file from a commit.
E.g. some changes have been applied to it in the work directory,
and the app being implemented no longer works properly.
It would be fine to have a look at that file, some commits ago,
when all worked fine.
Of course, it is possible to recover the entire old commit, or to
make a new branch, or checkout the file (which requires to save
the new one before), but the most simple and safe way is to
extract the file, giving it a new name.
That is possible, using this (hard to remember) trick:

git show HASH:file/path/name.ext > some_new_name.ext

Would not be better to have a "copy" command to copy a file from a commit
to a new one in the current directory?
This would make a git repository resemble a (readonly) filesystem, which
actually it is.
Note also that the ability to get from a repository what one has stored
in it is the most basic feature anyone wants from a repository.

Thank you
-Angelo Borsotti

```

## Ævar Arnfjörð Bjarmason, 2021-07-22 09:05

Subject: Re: Extracting a file
Message-ID: <871r7qvhhr.fsf@evledraar.gmail.com>
URL: https://gitlist.dev/e/871r7qvhhr.fsf%40evledraar.gmail.com
In-Reply-To: <CAB9Jk9AafnUQr6q8t=b4Dh0PZHUA=fKJmtXxxObuGpF_w-_2wQ@mail.gmail.com>

```

On Thu, Jul 22 2021, Angelo Borsotti wrote:

> Hi,
>
> sometimes there is a need to extract a file from a commit.
> E.g. some changes have been applied to it in the work directory,
> and the app being implemented no longer works properly.
> It would be fine to have a look at that file, some commits ago,
> when all worked fine.
> Of course, it is possible to recover the entire old commit, or to
> make a new branch, or checkout the file (which requires to save
> the new one before), but the most simple and safe way is to
> extract the file, giving it a new name.
> That is possible, using this (hard to remember) trick:
>
> git show HASH:file/path/name.ext > some_new_name.ext
>
> Would not be better to have a "copy" command to copy a file from a commit
> to a new one in the current directory?

That's an interesting feature request, FWIW you can do this now with:

    git mv A B &&
    git checkout HEAD -- A

I wonder if having a "git copy" for that would be more confusing that
not, i.e. a frequent difficulty new users used to have with git if they
were used to cvs/svn was to look for a "copy" command, thinking that
git's data model (like those older VCS's) needed the user to use a "mv"
or "copy" to track history.

On the other hand perhaps git's so thoroughly established that it's not
much of an educational issue anymore.

> This would make a git repository resemble a (readonly) filesystem, which
> actually it is.
> Note also that the ability to get from a repository what one has stored
> in it is the most basic feature anyone wants from a repository.

Git is actively not such a "read-only FS" in the sense of some version
control systems, i.e. needing to declare that you are now going to
"edit" the file etc.

It is for bare repositories, but a checkout explicitly concerns itself
with you doing arbitrary changes on the FS, and git needing to keep up.

So maybe there should be a "copy", but if your starting point for
wanting it is to make git behave like a read-only FS I don't think
that'll lead anywhere productive.

```

## Angelo Borsotti, 2021-07-22 09:46

Subject: Re: Extracting a file
Message-ID: <CAB9Jk9DqCR8C9qx6-gZmpTQfBAKnEupQTb1WkJgN3YOqSO0=2A@mail.gmail.com>
URL: https://gitlist.dev/e/CAB9Jk9DqCR8C9qx6-gZmpTQfBAKnEupQTb1WkJgN3YOqSO0%3D2A%40mail.gmail.com
In-Reply-To: <871r7qvhhr.fsf@evledraar.gmail.com>

```
Hi,

thank you for your quick reply.

Actually, I did not want to make git behave like a read-only filesystem,
but only to be able to get what is stored in it using some easy to remember
command.

I guess that:

    git mv A B &&
    git checkout HEAD -- A

renames file A in the work, current, directory to B, and then recovers
A from the
repository. This changes the file on which I am working. After having
read the old
A, and understood what changes I make that are not correct, I should delete A,
and rename B back to A.
If something gets wrong with this, I risk to damage my original A.
This is why it is
better not to change it, and instead get a copy of the old one with
another name,
which is what

git show HASH:file/path/name.ext > some_new_name.ext

does.

-Angelo

On Thu, 22 Jul 2021 at 11:13, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
>
>
> On Thu, Jul 22 2021, Angelo Borsotti wrote:
>
> > Hi,
> >
> > sometimes there is a need to extract a file from a commit.
> > E.g. some changes have been applied to it in the work directory,
> > and the app being implemented no longer works properly.
> > It would be fine to have a look at that file, some commits ago,
> > when all worked fine.
> > Of course, it is possible to recover the entire old commit, or to
> > make a new branch, or checkout the file (which requires to save
> > the new one before), but the most simple and safe way is to
> > extract the file, giving it a new name.
> > That is possible, using this (hard to remember) trick:
> >
> > git show HASH:file/path/name.ext > some_new_name.ext
> >
> > Would not be better to have a "copy" command to copy a file from a commit
> > to a new one in the current directory?
>
> That's an interesting feature request, FWIW you can do this now with:
>
>     git mv A B &&
>     git checkout HEAD -- A
>
> I wonder if having a "git copy" for that would be more confusing that
> not, i.e. a frequent difficulty new users used to have with git if they
> were used to cvs/svn was to look for a "copy" command, thinking that
> git's data model (like those older VCS's) needed the user to use a "mv"
> or "copy" to track history.
>
> On the other hand perhaps git's so thoroughly established that it's not
> much of an educational issue anymore.
>
> > This would make a git repository resemble a (readonly) filesystem, which
> > actually it is.
> > Note also that the ability to get from a repository what one has stored
> > in it is the most basic feature anyone wants from a repository.
>
> Git is actively not such a "read-only FS" in the sense of some version
> control systems, i.e. needing to declare that you are now going to
> "edit" the file etc.
>
> It is for bare repositories, but a checkout explicitly concerns itself
> with you doing arbitrary changes on the FS, and git needing to keep up.
>
> So maybe there should be a "copy", but if your starting point for
> wanting it is to make git behave like a read-only FS I don't think
> that'll lead anywhere productive.

```

## Jeff King, 2021-07-23 07:01

Subject: Re: Extracting a file
Message-ID: <YPppNYOO26xAq2fn@coredump.intra.peff.net>
URL: https://gitlist.dev/e/YPppNYOO26xAq2fn%40coredump.intra.peff.net
In-Reply-To: <CAB9Jk9DqCR8C9qx6-gZmpTQfBAKnEupQTb1WkJgN3YOqSO0=2A@mail.gmail.com>

```
On Thu, Jul 22, 2021 at 11:46:01AM +0200, Angelo Borsotti wrote:

> Actually, I did not want to make git behave like a read-only filesystem,
> but only to be able to get what is stored in it using some easy to remember
> command.
> 
> I guess that:
> 
>     git mv A B &&
>     git checkout HEAD -- A
> 
> renames file A in the work, current, directory to B, and then recovers
> A from the
> repository. This changes the file on which I am working. After having
> read the old
> A, and understood what changes I make that are not correct, I should delete A,
> and rename B back to A.
> If something gets wrong with this, I risk to damage my original A.
> This is why it is
> better not to change it, and instead get a copy of the old one with
> another name,
> which is what
> 
> git show HASH:file/path/name.ext > some_new_name.ext

You might also like "git checkout -p HASH -- A", which will let you pick
individual hunks from HASH:A and apply them to your working tree.

-Peff

```

## Angelo Borsotti, 2021-07-23 07:38

Subject: Re: Extracting a file
Message-ID: <CAB9Jk9Af-GKFUQCiyN9fKmjA1hOLBw9mc_FPFBHX1m1NAnbfmQ@mail.gmail.com>
URL: https://gitlist.dev/e/CAB9Jk9Af-GKFUQCiyN9fKmjA1hOLBw9mc_FPFBHX1m1NAnbfmQ%40mail.gmail.com
In-Reply-To: <YPppNYOO26xAq2fn@coredump.intra.peff.net>

```
Hi,

> You might also like "git checkout -p HASH -- A", which will let you pick
> individual hunks from HASH:A and apply them to your working tree.

This shows the differences between the committed and the current file,
in a patch
form, which is handy to apply to the current file to make it equal to
the old, but
not if I want to browse the old file and understand how it was before.
Moreover, the command ends by asking:

    Apply deletion to index and worktree [y,n,q,a,d,?]?

and when I must be very careful to provide the correct answer so as not to
damage my files.
So many alternatives to simply get a file from the repo, some of which
potentially
dangerous, show that there is a need for a simple, safe command to get it.

-Angelo

On Fri, 23 Jul 2021 at 09:01, Jeff King <peff@peff.net> wrote:
>
> On Thu, Jul 22, 2021 at 11:46:01AM +0200, Angelo Borsotti wrote:
>
> > Actually, I did not want to make git behave like a read-only filesystem,
> > but only to be able to get what is stored in it using some easy to remember
> > command.
> >
> > I guess that:
> >
> >     git mv A B &&
> >     git checkout HEAD -- A
> >
> > renames file A in the work, current, directory to B, and then recovers
> > A from the
> > repository. This changes the file on which I am working. After having
> > read the old
> > A, and understood what changes I make that are not correct, I should delete A,
> > and rename B back to A.
> > If something gets wrong with this, I risk to damage my original A.
> > This is why it is
> > better not to change it, and instead get a copy of the old one with
> > another name,
> > which is what
> >
> > git show HASH:file/path/name.ext > some_new_name.ext
>
> You might also like "git checkout -p HASH -- A", which will let you pick
> individual hunks from HASH:A and apply them to your working tree.
>
> -Peff

```

## Junio C Hamano, 2021-07-23 16:47

Subject: Re: Extracting a file
Message-ID: <xmqqa6mdou3n.fsf@gitster.g>
URL: https://gitlist.dev/e/xmqqa6mdou3n.fsf%40gitster.g
In-Reply-To: <CAB9Jk9Af-GKFUQCiyN9fKmjA1hOLBw9mc_FPFBHX1m1NAnbfmQ@mail.gmail.com>

```
Angelo Borsotti <angelo.borsotti@gmail.com> writes:

>> You might also like "git checkout -p HASH -- A", which will let you pick
>> individual hunks from HASH:A and apply them to your working tree.
>
> This shows the differences between the committed and the current file,
> in a patch
> form, which is handy to apply to the current file to make it equal to
> the old, but
> not if I want to browse the old file and understand how it was before.

Why doesn't a straight-forward "check out the path from an old
version" work?  That is

    git checkout $old_version -- path/to/file.ext

Is it because you have changes to path/to/file.ext already (in which
case "mv path/to/file.ext path/to/file.ext-saved" would be a quick
way to save it away)?

And then path/to/file.ext can be inspected to your heart's content,
and when you are done and want to go back to the current state, you
can do "git checkout HEAD -- path/to/file.ext" (followed by the
earlier "mv" in reverse)?

```

## Junio C Hamano, 2021-07-23 16:50

Subject: Re: Extracting a file
Message-ID: <xmqq5yx1oty6.fsf@gitster.g>
URL: https://gitlist.dev/e/xmqq5yx1oty6.fsf%40gitster.g
In-Reply-To: <YPppNYOO26xAq2fn@coredump.intra.peff.net>

```
Jeff King <peff@peff.net> writes:

> On Thu, Jul 22, 2021 at 11:46:01AM +0200, Angelo Borsotti wrote:
>
>> Actually, I did not want to make git behave like a read-only filesystem,
>> but only to be able to get what is stored in it using some easy to remember
>> command.
>> 
>> I guess that:
>> 
>>     git mv A B &&
>>     git checkout HEAD -- A
>> 
>> renames file A in the work, current, directory to B, and then recovers
>> A from the
>> repository. This changes the file on which I am working. After having
>> read the old
>> A, and understood what changes I make that are not correct, I should delete A,
>> and rename B back to A.
>> If something gets wrong with this, I risk to damage my original A.
>> This is why it is
>> better not to change it, and instead get a copy of the old one with
>> another name,
>> which is what
>> 
>> git show HASH:file/path/name.ext > some_new_name.ext
>
> You might also like "git checkout -p HASH -- A", which will let you pick
> individual hunks from HASH:A and apply them to your working tree.

There is

    git cat-file --textconv --filters HASH:A >my-temporary-file-to-inspect

which would not touch the index or any tracked working tree file,
other than the target of redirection.


```

## Felipe Contreras, 2021-07-23 18:17

Subject: Re: Extracting a file
Message-ID: <60fb079e38977_defb2087d@natae.notmuch>
URL: https://gitlist.dev/e/60fb079e38977_defb2087d%40natae.notmuch
In-Reply-To: <xmqq5yx1oty6.fsf@gitster.g>

```
Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
> 
> > On Thu, Jul 22, 2021 at 11:46:01AM +0200, Angelo Borsotti wrote:
> >
> >> Actually, I did not want to make git behave like a read-only filesystem,
> >> but only to be able to get what is stored in it using some easy to remember
> >> command.
> >> 
> >> I guess that:
> >> 
> >>     git mv A B &&
> >>     git checkout HEAD -- A
> >> 
> >> renames file A in the work, current, directory to B, and then recovers
> >> A from the
> >> repository. This changes the file on which I am working. After having
> >> read the old
> >> A, and understood what changes I make that are not correct, I should delete A,
> >> and rename B back to A.
> >> If something gets wrong with this, I risk to damage my original A.
> >> This is why it is
> >> better not to change it, and instead get a copy of the old one with
> >> another name,
> >> which is what
> >> 
> >> git show HASH:file/path/name.ext > some_new_name.ext
> >
> > You might also like "git checkout -p HASH -- A", which will let you pick
> > individual hunks from HASH:A and apply them to your working tree.
> 
> There is
> 
>     git cat-file --textconv --filters HASH:A >my-temporary-file-to-inspect
> 
> which would not touch the index or any tracked working tree file,
> other than the target of redirection.

Hmm, --textconv and --filters are incompatible with each other, did you
mean "--textconv | --filters"?

Also, this is simpler:

  git cat-file -p HASH:A

Although I don't know how that's better than Angelo's `git show`.

FTR I do often use `git show commit:file` myself. I'm not sure if
we could do something particularly better than that.

-- 
Felipe Contreras

```
