git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [FR] Allow `git stash create` to include untracked changes
@ 2019-10-26 14:38 dev
  2019-10-28  1:51 ` Junio C Hamano
  0 siblings, 1 reply; 5+ messages in thread
From: dev @ 2019-10-26 14:38 UTC (permalink / raw)
  To: git

Hello,

TL;DR:
Would it be possible for `git stash create` to include untracked changes 
(probably the same way `git stash push --include-untracked` does)?

---

I'm having some trouble with `git stash create`.

Currently, in my script (https://github.com/sarpik/git-backup), I 
essentially want to create a stash from untracked changes, create a 
branch from the stash, push the branch to a remote repository & pop the 
stash back, while keeping the backup branch. A remote stash, if you may.

I'm able to do this with regular `git stash push --include-untracked` 
and `git stash pop` commands, but there're some issues I've encountered 
and I believe that this is not the optimal solution.
This could be solved with `git stash create`, but it's unable to (as far 
as I know) create the stash with untracked/all changes.

Once again:
Would it be possible for `git stash create` to include untracked changes 
(probably the same way `git stash push --include-untracked` does)?

---

The issues I've so far encountered were:

Say I'm in an untracked directory. If I run `git stash push 
--include-untracked` and stay in this untracked directory, which 
actually does not exist anymore, and then run `git stash pop`, I get 
fatal errors and I'm unable to do anything else:

fatal: Unable to read current working directory: No such file or 
directory

(please see https://github.com/sarpik/git-backup/issues/10 and 
specifically, 
https://github.com/sarpik/git-backup/issues/10#issuecomment-546599631)

This could probably be solved by `cd`ing up until I'm inside the same 
directory where `.git/` folder is placed and only then running `git 
stash push --include-untracked` and `git stash pop`.

Even then, this approach still kind of sucks, because you're still 
temporarily stashing user's changes. I'd like to avoid this and `git 
stash create` seems like the perfect solution, if only it could include 
untracked changes.

Thank you very much - please let me know if there's anything else I 
could help with.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [FR] Allow `git stash create` to include untracked changes
  2019-10-26 14:38 [FR] Allow `git stash create` to include untracked changes dev
@ 2019-10-28  1:51 ` Junio C Hamano
  2019-10-28 16:03   ` Kipras Melnikovas
  2019-10-29  7:29   ` Johannes Schindelin
  0 siblings, 2 replies; 5+ messages in thread
From: Junio C Hamano @ 2019-10-28  1:51 UTC (permalink / raw)
  To: dev, Paul-Sebastian Ungureanu; +Cc: git

dev@kipras.org writes:

> Would it be possible for `git stash create` to include untracked
> changes (probably the same way `git stash push --include-untracked`
> does)?

Doesn't the subcommand have -u/--include-untracked option?

... goes and looks git-stash.sh ...

create_stash () {

	prepare_fallback_ident

	stash_msg=
	untracked=
	while test $# != 0
	do
		case "$1" in
		-m|--message)
			...
			;;
		-u|--include-untracked)
			shift
			untracked=${1?"BUG: create_stash () -u requires an argument"}
			;;
		...
	done
	...

It is entirely possible that with recent push to rewrite scripted
Porcelain commands to builtin/, we may have lost a feature or two
by accident.

  ... goes and checks ...

And it does appear that builtin/stash.c::create_stash() lacks
support for command line arguments since d4788af8 ("stash: convert
create to builtin", 2019-02-25).

Would doing

	export GIT_TEST_STASH_USE_BUILTIN=no

or

	git config --global stash.usebuiltin no

help in the meantime???

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Re: [FR] Allow `git stash create` to include untracked changes
  2019-10-28  1:51 ` Junio C Hamano
@ 2019-10-28 16:03   ` Kipras Melnikovas
  2019-10-29  7:29   ` Johannes Schindelin
  1 sibling, 0 replies; 5+ messages in thread
From: Kipras Melnikovas @ 2019-10-28 16:03 UTC (permalink / raw)
  To: gitster; +Cc: dev, git, ungureanupaulsebastian

Hello,
thank you for the info.

It seems like neither worked:

export GIT_TEST_STASH_USE_BUILTIN=no
git config --global stash.usebuiltin no

The untracked files are still not stashed with `git stash create -u [some-argument]`, but are stashed successfully with `git stash push -u`,
so unless I'm doing something wrong, this also doesn't help, sadly.

Also, if there are no modified changes (only untracked ones), then `git stash create [-u [some-arg]]` (the non-builtin stash) will not even give you a commit object's name, thus it probably does not create the commit object at all.

Also, the manual page of git-stash(1) not mention the `--include-untracked` option - this is why I posted in the first place.

$ man git-stash
...
git stash create [<message>]
git stash store [-m|--message <message>] [-q|--quiet] <commit>
...

---

Is there any chance to

* get the builtin stash to support `--include-untracked` option?

* figure out if the legacy stash also works as intended with the `-u [some-arg]` option
	* when there aren't any changes, except untracked/ignored ones, the commit object doesn't seem to be created (printed) at all
	* why does it even require an argument?

* update the manual page for git-stash(1)

* check if everything's fine with `git stash store` too, just in case:D

Is there anything else I need to do to get this issue reported or are you guys taking care of it?

---

My stuff:

$ git --version
git version 2.23.0

$ uname -a
Linux arch-usb 5.3.7-arch1-1-ARCH #1 SMP PREEMPT Fri Oct 18 00:17:03 UTC 2019 x86_64 GNU/Linux

Thank you for your time and support:)
Kipras


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [FR] Allow `git stash create` to include untracked changes
  2019-10-28  1:51 ` Junio C Hamano
  2019-10-28 16:03   ` Kipras Melnikovas
@ 2019-10-29  7:29   ` Johannes Schindelin
  2019-10-31 13:40     ` Thomas Gummerer
  1 sibling, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2019-10-29  7:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: dev, Paul-Sebastian Ungureanu, git

Hi Junio,

On Mon, 28 Oct 2019, Junio C Hamano wrote:

> dev@kipras.org writes:
>
> > Would it be possible for `git stash create` to include untracked
> > changes (probably the same way `git stash push --include-untracked`
> > does)?
>
> Doesn't the subcommand have -u/--include-untracked option?
>
> ... goes and looks git-stash.sh ...
>
> create_stash () {

Careful, this is a false friend. It _is_ work horse of `git stash
create`, but not _quite_ in the way you think:

-- snap --
create)
	shift
	create_stash -m "$*" && echo "$w_commit"
	;;
-- snap --

So what is the reason for the existence of this command-line parsing:

>
> 	prepare_fallback_ident
>
> 	stash_msg=
> 	untracked=
> 	while test $# != 0
> 	do
> 		case "$1" in
> 		-m|--message)
> 			...
> 			;;
> 		-u|--include-untracked)
> 			shift
> 			untracked=${1?"BUG: create_stash () -u requires an argument"}
> 			;;
> 		...
> 	done
> 	...

Why, `push_stash` calls `create_stash` ;-)

-- snip --
push_stash () {
	[...]
        untracked=
	[...]
                -u|--include-untracked)
			untracked=untracked
			;;
	[...]
        create_stash -m "$stash_msg" -u "$untracked" -- "$@"
	[...]
-- snap --

So the reason that `git stash create -u ...` does not work is that it
never was designed to work ;-)

> It is entirely possible that with recent push to rewrite scripted
> Porcelain commands to builtin/, we may have lost a feature or two
> by accident.
>
>   ... goes and checks ...
>
> And it does appear that builtin/stash.c::create_stash() lacks
> support for command line arguments since d4788af8 ("stash: convert
> create to builtin", 2019-02-25).
>
> Would doing
>
> 	export GIT_TEST_STASH_USE_BUILTIN=no
>
> or
>
> 	git config --global stash.usebuiltin no
>
> help in the meantime???

Well, given this code in `builtin/stash.c`, I would imagine that `git
stash push -u ...` works both in the legacy and the built-in version of
`git stash`:

-- snip --
static int push_stash(int argc, const char **argv, const char *prefix)
{
	int keep_index = -1;
	int patch_mode = 0;
	int include_untracked = 0;
	int quiet = 0;
	const char *stash_msg = NULL;
	struct pathspec ps;
	struct option options[] = {
		OPT_BOOL('k', "keep-index", &keep_index,
			 N_("keep index")),
		OPT_BOOL('p', "patch", &patch_mode,
			 N_("stash in patch mode")),
		OPT__QUIET(&quiet, N_("quiet mode")),
		OPT_BOOL('u', "include-untracked", &include_untracked,
			 N_("include untracked files in stash")),
		OPT_SET_INT('a', "all", &include_untracked,
			    N_("include ignore files"), 2),
		OPT_STRING('m', "message", &stash_msg, N_("message"),
			   N_("stash message")),
		OPT_END()
	};

	if (argc)
		argc = parse_options(argc, argv, prefix, options,
				     git_stash_push_usage,
				     0);

	parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
		       prefix, argv);
	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
			     include_untracked);
}
-- snap --

So why does `git stash create -u ...` not work? Because the original
design of `git stash create` never intended to take any command-line
arguments other than the stash message. And that design can obviously
not be fixed without breaking backwards compatibility.

What we _could_ do is to add a new command-line option to `git stash
push` that would make it behave like the `create` subsubcommand: _not_
update the `refs/stash` ref but instead print the commit hash.

I am not quite sure how to call this option (`--ephemeral` came to my
mind, as the created commit is not reachable from anywhere and is hence
subject to garbage collection).

A completely different approach would be to allow overriding the ref to
store the stash in, with an empty value triggering the mode where the
ref is not updated but the commit hash would be printed instead. I am
thinking of something like `git stash -r '' push ...`, starting with
this patch:

-- snip --
diff --git a/builtin/stash.c b/builtin/stash.c
index bb4f6d8d762..43b0a155b1d 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1553,6 +1553,8 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
 	struct argv_array args = ARGV_ARRAY_INIT;

 	struct option options[] = {
+		OPT_STRING('r', "ref", &ref_stash, N_("ref"),
+			   N_("override `refs/stash`")),
 		OPT_END()
 	};

-- snap --

The biggest trick will be to make all the code paths safe that assume
that `ref_stash` refers to a valid ref ;-)

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [FR] Allow `git stash create` to include untracked changes
  2019-10-29  7:29   ` Johannes Schindelin
@ 2019-10-31 13:40     ` Thomas Gummerer
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Gummerer @ 2019-10-31 13:40 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, dev, Paul-Sebastian Ungureanu, git

On 10/29, Johannes Schindelin wrote:
> So why does `git stash create -u ...` not work? Because the original
> design of `git stash create` never intended to take any command-line
> arguments other than the stash message. And that design can obviously
> not be fixed without breaking backwards compatibility.

Yup that's exactly right.  Not breaking this sort of backwards
compatibility is also why we have both 'git stash save' and 'git stash
push' nowadays.

We did have a similar conversation back when 'git stash push' was
introduced [1].  We almost decided this regression would be okay, but
in the end went with calling 'create_stash -m "$*"' internally to
circumvent the problem.  Now that somebody has an actual usecase we
may or may not find this "regression" acceptable.  I don't have a
strong opinion about it, so this is just to add a little bit of
context here.

[1]: https://public-inbox.org/git/20170206155606.xgkmhg656vuc6uki@sigill.intra.peff.net/

> What we _could_ do is to add a new command-line option to `git stash
> push` that would make it behave like the `create` subsubcommand: _not_
> update the `refs/stash` ref but instead print the commit hash.
> 
> I am not quite sure how to call this option (`--ephemeral` came to my
> mind, as the created commit is not reachable from anywhere and is hence
> subject to garbage collection).
> 
> A completely different approach would be to allow overriding the ref to
> store the stash in, with an empty value triggering the mode where the
> ref is not updated but the commit hash would be printed instead. I am
> thinking of something like `git stash -r '' push ...`, starting with
> this patch:
> 
> -- snip --
> diff --git a/builtin/stash.c b/builtin/stash.c
> index bb4f6d8d762..43b0a155b1d 100644
> --- a/builtin/stash.c
> +++ b/builtin/stash.c
> @@ -1553,6 +1553,8 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
>  	struct argv_array args = ARGV_ARRAY_INIT;
> 
>  	struct option options[] = {
> +		OPT_STRING('r', "ref", &ref_stash, N_("ref"),
> +			   N_("override `refs/stash`")),
>  		OPT_END()
>  	};
> 
> -- snap --
> 
> The biggest trick will be to make all the code paths safe that assume
> that `ref_stash` refers to a valid ref ;-)
> 
> Ciao,
> Dscho

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-10-31 13:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-26 14:38 [FR] Allow `git stash create` to include untracked changes dev
2019-10-28  1:51 ` Junio C Hamano
2019-10-28 16:03   ` Kipras Melnikovas
2019-10-29  7:29   ` Johannes Schindelin
2019-10-31 13:40     ` Thomas Gummerer

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).