[Bug 2026319] Re: stash: git does not recover untracked files during a pop/apply on conflict

Matthew Ruffell 2026319 at bugs.launchpad.net
Wed Aug 9 04:32:24 UTC 2023


Performing verification for Jammy. I installed git 2.34.1-1ubuntu1.9
from -updates:

$ sudo apt-cache policy git | grep Installed
  Installed: 1:2.34.1-1ubuntu1.9

Running the reproducer:

$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
Initialized empty Git repository in /home/ubuntu/test/.git/
$ git config --global user.email "you at example.com"
$ git config --global user.name "Your Name"
$ echo contents > original-file.txt
$ git add original-file.txt
$ git commit -m "Creating the file"
[master (root-commit) 0a02f82] Creating the file
 1 file changed, 1 insertion(+)
 create mode 100644 original-file.txt
$ echo foo > new-file.txt
$ echo contents2 > original-file.txt
$ git stash push -u
Saved working directory and index state WIP on master: 0a02f82 Creating the file
$ echo contents3 > original-file.txt
$ git commit -am "Altering the file"
[master 4533623] Altering the file
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git stash pop
Auto-merging original-file.txt
CONFLICT (content): Merge conflict in original-file.txt
The stash entry is kept in case you need it again.
$ cat new-file.txt
cat: new-file.txt: No such file or directory

Upon conflict we don't get a full explanation of what is outstanding such as
"unmerged paths" and "untracked files". The untracked file of new-file.txt is
missing and has not been restored to the working directory.

I then enabled -proposed and installed git 2.34.1-1ubuntu1.10 and re-ran the
reproducer:

$ sudo apt-cache policy git | grep Installed
  Installed: 1:2.34.1-1ubuntu1.10

$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
Initialized empty Git repository in /home/ubuntu/proposed/.git/
$ echo contents > original-file.txt
$ git add original-file.txt
$ git commit -m "Creating the file"
[master (root-commit) 0508716] Creating the file
 1 file changed, 1 insertion(+)
 create mode 100644 original-file.txt
$ echo foo > new-file.txt
$ echo contents2 > original-file.txt
$ git stash push -u
Saved working directory and index state WIP on master: 0508716 Creating the file
$ echo contents3 > original-file.txt
$ git commit -am "Altering the file"
[master b6d8396] Altering the file
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git stash pop
Auto-merging original-file.txt
CONFLICT (content): Merge conflict in original-file.txt
On branch master
Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
	both modified:   original-file.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	new-file.txt

no changes added to commit (use "git add" and/or "git commit -a")
The stash entry is kept in case you need it again.
$ cat new-file.txt
foo

This time we get the inline "git status" when the conflict arises, and the
untracked file is restored correctly, along with its contents.

The unit test also executes correctly, if we examine the buildlog:

https://launchpadlibrarian.net/681062898/buildlog_ubuntu-jammy-
amd64.git_1%3A2.34.1-1ubuntu1.10_BUILDING.txt.gz

...
expecting success of 3903.111 'restore untracked files even when we hit conflicts': 
	git init restore_untracked_after_conflict &&
	(
		cd restore_untracked_after_conflict &&

		echo hi >a &&
		echo there >b &&
		git add . &&
		git commit -m first &&
		echo hello >a &&
		echo something >c &&

                git stash push --include-untracked &&

		echo conflict >a &&
		git add a &&
		git commit -m second &&

                test_must_fail git stash pop &&

		test_path_is_file c
	)

Initialized empty Git repository in /<<PKGBUILDDIR>>/t/trash directory.t3903-stash/restore_untracked_after_conflict/.git/
[main (root-commit) 1dc9add] first
 Author: A U Thor <author at example.com>
 2 files changed, 2 insertions(+)
 create mode 100644 a
 create mode 100644 b
Saved working directory and index state WIP on main: 1dc9add first
[main 9e228ae] second
 Author: A U Thor <author at example.com>
 1 file changed, 1 insertion(+), 1 deletion(-)
Merging Updated upstream with Stashed changes
Merging:
virtual Updated upstream
virtual Stashed changes
found 1 common ancestor:
virtual c017b915e83a1d32cc014487285a63a4712e6201
Auto-merging a
CONFLICT (content): Merge conflict in a
On branch main
Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
	both modified:   a

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	c

no changes added to commit (use "git add" and/or "git commit -a")
The stash entry is kept in case you need it again.
ok 111 - restore untracked files even when we hit conflicts
...

The package in -proposed fixes the issue. Happy to mark as verified for
Jammy.

** Tags removed: verification-needed verification-needed-jammy
** Tags added: verification-done-jammy

-- 
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to git in Ubuntu.
https://bugs.launchpad.net/bugs/2026319

Title:
  stash: git does not recover untracked files during a pop/apply on
  conflict

Status in git package in Ubuntu:
  Fix Released
Status in git source package in Jammy:
  Fix Committed

Bug description:
  [Impact]

  On jammy, untracked files in a working directory are not recovered if
  you have previously stashed them, if there happens to be a merge
  conflict when it comes to pop/apply the stash during rebasing
  operations.

  This is a problem because files users intentionally place in their
  working directories are lost, which could lead to user's losing their
  data or recent development effort.

  The only workaround is to ensure that doing a pop/apply will not cause
  any merge conflicts, or to ensure that all of your files are added and
  committed.

  [Testcase]

  On a Jammy system:

  $ git init
  $ echo contents > original-file.txt
  $ git add original-file.txt
  $ git commit -m "Creating the file"

  # Create a new file, modify an old one, stash
  $ echo foo > new-file.txt
  $ echo contents2 > original-file.txt
  $ git stash push -u

  # Modify the old file in a different way, commit
  $ echo contents3 > original-file.txt
  $ git commit -am "Altering the file"

  # Apply the stash, see conflict, but what about the new file?
  $ git stash pop
  $ cat new-file.txt
  cat: new-file.txt: No such file or directory
  # "new-file.txt" is expected to exist, but is gone

  There is a test package available in the following ppa:

  https://launchpad.net/~mruffell/+archive/ubuntu/sf363767-test

  When installed, "new-file.txt" exists and is able to be read.

  $ git stash pop
  Auto-merging original-file.txt
  CONFLICT (content): Merge conflict in original-file.txt
  On branch master
  Unmerged paths:
    (use "git restore --staged <file>..." to unstage)
    (use "git add <file>..." to mark resolution)
  	both modified:   original-file.txt

  Untracked files:
    (use "git add <file>..." to include in what will be committed)
  	new-file.txt

  no changes added to commit (use "git add" and/or "git commit -a")
  The stash entry is kept in case you need it again.
  $ cat new-file.txt
  foo

  [Where problems could occur]

  We are changing how git restores untracked files during a pop/apply
  operation during a stash. Currently, these untracked files are "lost"
  i.e. they vanish from the user's working directory. It currently is
  possible to get them back, but you need to dig around in orphaned
  commits, and since they no longer have any references anymore, even
  finding their commit hashes is difficult.

  With the patch applied, user's untracked files will no longer vanish
  on stash pop/apply, and while I don't think user's would be surprised
  to find files they intentionally placed in the working directory
  safely restored, there is a change in behaviour that these files are
  now restored, instead of being "deleted" or lost forever. It is
  unlikely any users have built workflows that depend on untracked files
  being removed on a stash pop/apply, versus users who intentionally put
  untracked files in their working directory only to find they have lost
  them forever upon stashing.

  If a regression were to occur, it could break worldwide development
  workflows, due to git being the most popular revision control system,
  and as such, any changes are high risk.

  [Other info]

  This was fixed upstream by the following commit in 2.35.0:

  commit 71cade5a0b172ece7edf0ccb4420dd5b9a07e71a
  Author: Elijah Newren <newren at gmail.com>
  Date: Tue, 4 Jan 2022 23:04:58 +0000
  Subject: stash: do not return before restoring untracked files
  Link: https://github.com/git/git/commit/71cade5a0b172ece7edf0ccb4420dd5b9a07e71a

  The issue was introduced in commit bee8691 ("stash: restore untracked
  files AFTER restoring tracked files" in version 2.33.1, so Focal is
  not affected. Since the fix is in 2.35.0, kinetic is already fixed.

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/git/+bug/2026319/+subscriptions




More information about the foundations-bugs mailing list