git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Aleksandr Pryimak <tramsmm-mirror@yandex.ru>
Cc: git@vger.kernel.org
Subject: Re: git stash data loss
Date: Fri, 27 Jul 2012 09:29:53 -0400	[thread overview]
Message-ID: <20120727132953.GA8263@sigill.intra.peff.net> (raw)
In-Reply-To: <55831343358368@web1e.yandex.ru>

On Fri, Jul 27, 2012 at 07:06:08AM +0400, Aleksandr Pryimak wrote:

> I also recreated it
> 
> aleksandr@beast:/tmp/test$ git init
> Initialized empty Git repository in /tmp/test/.git/
> aleksandr@beast:/tmp/test$ touch x
> aleksandr@beast:/tmp/test$ git add x
> aleksandr@beast:/tmp/test$ git commit -m "Initial"
> [master (root-commit) d3569a0] Initial
>  0 files changed, 0 insertions(+), 0 deletions(-)
>  create mode 100644 x

OK, so we have "x" as a tracked file.

> aleksandr@beast:/tmp/test$ rm x
> aleksandr@beast:/tmp/test$ mkdir x/
> aleksandr@beast:/tmp/test$ ls
> x

And then we remove it in favor of a directory. Note that git does not
track directories directly, only files inside them. So from git's
perspective, the working tree has no content in it at all.

> aleksandr@beast:/tmp/test$ git stash
> Saved working directory and index state WIP on master: d3569a0 Initial
> HEAD is now at d3569a0 Initial

And now we stash it. That will stash the working tree removal of x. It
will not stash anything about the new directory x, because it has no
content inside it.

> aleksandr@beast:/tmp/test$ ls
> x
> aleksandr@beast:/tmp/test$ git stash pop
> Removing x
> # On branch master
> # Changes not staged for commit:
> #   (use "git add/rm <file>..." to update what will be committed)
> #   (use "git checkout -- <file>..." to discard changes in working directory)
> #
> #	deleted:    x
> #
> no changes added to commit (use "git add" and/or "git commit -a")
> Dropped refs/stash@{0} (c500443ae16cf0d846b195cb97eb388dec5f440e)
> aleksandr@beast:/tmp/test$ ls

And your stash pop restores the deletion of "x". It does _not_ reinstate
the directory "x", because as I stated above, that is not part of the
stash.

So what is the data loss? That the "mkdir x" was lost? That has nothing
to do with stash, but rather the fact that git does not track empty
directories. You could see the same thing with:
 
  mkdir x && git commit -a

which will not record your mkdir at all. In other words, this is by
design.

If we put actual files inside "x", which git does track, then they would
be part of the stash, and should be properly retained. But they're not:

  $ rm x && mkdir x && echo foo >x/file

Now we have some precious contents in the form of "x/file". They are
untracked by git, but git should be careful about removing them.

  $ git stash
  Saved working directory and index state WIP on master: 2d32d3a initial
  HEAD is now at 2d32d3a initial
  $ ls -l x
  -rw-r--r-- 1 peff peff 0 Jul 27 09:19 x
  $ git stash show --raw
  :100644 000000 e69de29... 0000000... D  x

Now this _is_ data loss. Stash blows away untracked files inside the
directory, but does not record them in the resulting stash. And that
should be fixed.

With "-u", I'd expect stash to include the untracked file x/foo in the
stash. Without "-u", I'd expect stash to fail, since it would be
deleting untracked files.

-Peff

  reply	other threads:[~2012-07-27 13:30 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-27  3:06 git stash data loss Aleksandr Pryimak
2012-07-27 13:29 ` Jeff King [this message]
2012-07-27 13:50   ` Jeff King
2012-08-17  3:30     ` Junio C Hamano
2012-08-21  6:55       ` Jeff King
2012-09-14 23:04         ` Junio C Hamano
2012-07-27 14:21   ` Aleksandr Priymak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120727132953.GA8263@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=tramsmm-mirror@yandex.ru \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).