{"thread":{"id":"52127","subject":"[FR] Allow `git stash create` to include untracked changes","startedAt":"2019-10-26T14:59:57Z","lastAt":"2019-10-31T13:40:39Z","messageCount":5,"participants":["dev@kipras.org","Junio C Hamano","Kipras Melnikovas","Johannes Schindelin","Thomas Gummerer"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"384912","messageId":"d02ddc0db596771820b0cfdfae5b1504@kipras.org","threadId":"52127","inReplyTo":null,"subject":"[FR] Allow `git stash create` to include untracked changes","fromName":"","fromEmail":"dev@kipras.org","sentAt":"2019-10-26T14:38:34Z","receivedAt":"2019-10-26T14:59:57Z","isPatch":false,"sender":{"key":"dev@kipras.org","avatar":null},"body":"Hello,\n\nTL;DR:\nWould it be possible for `git stash create` to include untracked changes \n(probably the same way `git stash push --include-untracked` does)?\n\n---\n\nI'm having some trouble with `git stash create`.\n\nCurrently, in my script (https://github.com/sarpik/git-backup), I \nessentially want to create a stash from untracked changes, create a \nbranch from the stash, push the branch to a remote repository & pop the \nstash back, while keeping the backup branch. A remote stash, if you may.\n\nI'm able to do this with regular `git stash push --include-untracked` \nand `git stash pop` commands, but there're some issues I've encountered \nand I believe that this is not the optimal solution.\nThis could be solved with `git stash create`, but it's unable to (as far \nas I know) create the stash with untracked/all changes.\n\nOnce again:\nWould it be possible for `git stash create` to include untracked changes \n(probably the same way `git stash push --include-untracked` does)?\n\n---\n\nThe issues I've so far encountered were:\n\nSay I'm in an untracked directory. If I run `git stash push \n--include-untracked` and stay in this untracked directory, which \nactually does not exist anymore, and then run `git stash pop`, I get \nfatal errors and I'm unable to do anything else:\n\nfatal: Unable to read current working directory: No such file or \ndirectory\n\n(please see https://github.com/sarpik/git-backup/issues/10 and \nspecifically, \nhttps://github.com/sarpik/git-backup/issues/10#issuecomment-546599631)\n\nThis could probably be solved by `cd`ing up until I'm inside the same \ndirectory where `.git/` folder is placed and only then running `git \nstash push --include-untracked` and `git stash pop`.\n\nEven then, this approach still kind of sucks, because you're still \ntemporarily stashing user's changes. I'd like to avoid this and `git \nstash create` seems like the perfect solution, if only it could include \nuntracked changes.\n\nThank you very much - please let me know if there's anything else I \ncould help with.\n"},{"id":"384958","messageId":"xmqqa79lbpte.fsf@gitster-ct.c.googlers.com","threadId":"52127","inReplyTo":"d02ddc0db596771820b0cfdfae5b1504@kipras.org","subject":"Re: [FR] Allow `git stash create` to include untracked changes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-10-28T01:51:09Z","receivedAt":"2019-10-28T01:51:18Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"dev@kipras.org writes:\n\n> Would it be possible for `git stash create` to include untracked\n> changes (probably the same way `git stash push --include-untracked`\n> does)?\n\nDoesn't the subcommand have -u/--include-untracked option?\n\n... goes and looks git-stash.sh ...\n\ncreate_stash () {\n\n\tprepare_fallback_ident\n\n\tstash_msg=\n\tuntracked=\n\twhile test $# != 0\n\tdo\n\t\tcase \"$1\" in\n\t\t-m|--message)\n\t\t\t...\n\t\t\t;;\n\t\t-u|--include-untracked)\n\t\t\tshift\n\t\t\tuntracked=${1?\"BUG: create_stash () -u requires an argument\"}\n\t\t\t;;\n\t\t...\n\tdone\n\t...\n\nIt is entirely possible that with recent push to rewrite scripted\nPorcelain commands to builtin/, we may have lost a feature or two\nby accident.\n\n  ... goes and checks ...\n\nAnd it does appear that builtin/stash.c::create_stash() lacks\nsupport for command line arguments since d4788af8 (\"stash: convert\ncreate to builtin\", 2019-02-25).\n\nWould doing\n\n\texport GIT_TEST_STASH_USE_BUILTIN=no\n\nor\n\n\tgit config --global stash.usebuiltin no\n\nhelp in the meantime???\n"},{"id":"385007","messageId":"20191028160305.169851-1-kipras@kipras.org","threadId":"52127","inReplyTo":"xmqqa79lbpte.fsf@gitster-ct.c.googlers.com","subject":"Re: Re: [FR] Allow `git stash create` to include untracked changes","fromName":"Kipras Melnikovas","fromEmail":"kipras@kipras.org","sentAt":"2019-10-28T16:03:05Z","receivedAt":"2019-10-28T16:30:02Z","isPatch":false,"sender":{"key":"kipras@kipras.org","avatar":"https://avatars.githubusercontent.com/u/29430509?v=4"},"body":"Hello,\nthank you for the info.\n\nIt seems like neither worked:\n\nexport GIT_TEST_STASH_USE_BUILTIN=no\ngit config --global stash.usebuiltin no\n\nThe untracked files are still not stashed with `git stash create -u [some-argument]`, but are stashed successfully with `git stash push -u`,\nso unless I'm doing something wrong, this also doesn't help, sadly.\n\nAlso, 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.\n\nAlso, the manual page of git-stash(1) not mention the `--include-untracked` option - this is why I posted in the first place.\n\n$ man git-stash\n...\ngit stash create [<message>]\ngit stash store [-m|--message <message>] [-q|--quiet] <commit>\n...\n\n---\n\nIs there any chance to\n\n* get the builtin stash to support `--include-untracked` option?\n\n* figure out if the legacy stash also works as intended with the `-u [some-arg]` option\n\t* when there aren't any changes, except untracked/ignored ones, the commit object doesn't seem to be created (printed) at all\n\t* why does it even require an argument?\n\n* update the manual page for git-stash(1)\n\n* check if everything's fine with `git stash store` too, just in case:D\n\nIs there anything else I need to do to get this issue reported or are you guys taking care of it?\n\n---\n\nMy stuff:\n\n$ git --version\ngit version 2.23.0\n\n$ uname -a\nLinux arch-usb 5.3.7-arch1-1-ARCH #1 SMP PREEMPT Fri Oct 18 00:17:03 UTC 2019 x86_64 GNU/Linux\n\nThank you for your time and support:)\nKipras\n\n"},{"id":"385047","messageId":"nycvar.QRO.7.76.6.1910290806310.46@tvgsbejvaqbjf.bet","threadId":"52127","inReplyTo":"xmqqa79lbpte.fsf@gitster-ct.c.googlers.com","subject":"Re: [FR] Allow `git stash create` to include untracked changes","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2019-10-29T07:29:39Z","receivedAt":"2019-10-29T07:30:03Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Junio,\n\nOn Mon, 28 Oct 2019, Junio C Hamano wrote:\n\n> dev@kipras.org writes:\n>\n> > Would it be possible for `git stash create` to include untracked\n> > changes (probably the same way `git stash push --include-untracked`\n> > does)?\n>\n> Doesn't the subcommand have -u/--include-untracked option?\n>\n> ... goes and looks git-stash.sh ...\n>\n> create_stash () {\n\nCareful, this is a false friend. It _is_ work horse of `git stash\ncreate`, but not _quite_ in the way you think:\n\n-- snap --\ncreate)\n\tshift\n\tcreate_stash -m \"$*\" && echo \"$w_commit\"\n\t;;\n-- snap --\n\nSo what is the reason for the existence of this command-line parsing:\n\n>\n> \tprepare_fallback_ident\n>\n> \tstash_msg=\n> \tuntracked=\n> \twhile test $# != 0\n> \tdo\n> \t\tcase \"$1\" in\n> \t\t-m|--message)\n> \t\t\t...\n> \t\t\t;;\n> \t\t-u|--include-untracked)\n> \t\t\tshift\n> \t\t\tuntracked=${1?\"BUG: create_stash () -u requires an argument\"}\n> \t\t\t;;\n> \t\t...\n> \tdone\n> \t...\n\nWhy, `push_stash` calls `create_stash` ;-)\n\n-- snip --\npush_stash () {\n\t[...]\n        untracked=\n\t[...]\n                -u|--include-untracked)\n\t\t\tuntracked=untracked\n\t\t\t;;\n\t[...]\n        create_stash -m \"$stash_msg\" -u \"$untracked\" -- \"$@\"\n\t[...]\n-- snap --\n\nSo the reason that `git stash create -u ...` does not work is that it\nnever was designed to work ;-)\n\n> It is entirely possible that with recent push to rewrite scripted\n> Porcelain commands to builtin/, we may have lost a feature or two\n> by accident.\n>\n>   ... goes and checks ...\n>\n> And it does appear that builtin/stash.c::create_stash() lacks\n> support for command line arguments since d4788af8 (\"stash: convert\n> create to builtin\", 2019-02-25).\n>\n> Would doing\n>\n> \texport GIT_TEST_STASH_USE_BUILTIN=no\n>\n> or\n>\n> \tgit config --global stash.usebuiltin no\n>\n> help in the meantime???\n\nWell, given this code in `builtin/stash.c`, I would imagine that `git\nstash push -u ...` works both in the legacy and the built-in version of\n`git stash`:\n\n-- snip --\nstatic int push_stash(int argc, const char **argv, const char *prefix)\n{\n\tint keep_index = -1;\n\tint patch_mode = 0;\n\tint include_untracked = 0;\n\tint quiet = 0;\n\tconst char *stash_msg = NULL;\n\tstruct pathspec ps;\n\tstruct option options[] = {\n\t\tOPT_BOOL('k', \"keep-index\", &keep_index,\n\t\t\t N_(\"keep index\")),\n\t\tOPT_BOOL('p', \"patch\", &patch_mode,\n\t\t\t N_(\"stash in patch mode\")),\n\t\tOPT__QUIET(&quiet, N_(\"quiet mode\")),\n\t\tOPT_BOOL('u', \"include-untracked\", &include_untracked,\n\t\t\t N_(\"include untracked files in stash\")),\n\t\tOPT_SET_INT('a', \"all\", &include_untracked,\n\t\t\t    N_(\"include ignore files\"), 2),\n\t\tOPT_STRING('m', \"message\", &stash_msg, N_(\"message\"),\n\t\t\t   N_(\"stash message\")),\n\t\tOPT_END()\n\t};\n\n\tif (argc)\n\t\targc = parse_options(argc, argv, prefix, options,\n\t\t\t\t     git_stash_push_usage,\n\t\t\t\t     0);\n\n\tparse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,\n\t\t       prefix, argv);\n\treturn do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,\n\t\t\t     include_untracked);\n}\n-- snap --\n\nSo why does `git stash create -u ...` not work? Because the original\ndesign of `git stash create` never intended to take any command-line\narguments other than the stash message. And that design can obviously\nnot be fixed without breaking backwards compatibility.\n\nWhat we _could_ do is to add a new command-line option to `git stash\npush` that would make it behave like the `create` subsubcommand: _not_\nupdate the `refs/stash` ref but instead print the commit hash.\n\nI am not quite sure how to call this option (`--ephemeral` came to my\nmind, as the created commit is not reachable from anywhere and is hence\nsubject to garbage collection).\n\nA completely different approach would be to allow overriding the ref to\nstore the stash in, with an empty value triggering the mode where the\nref is not updated but the commit hash would be printed instead. I am\nthinking of something like `git stash -r '' push ...`, starting with\nthis patch:\n\n-- snip --\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex bb4f6d8d762..43b0a155b1d 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -1553,6 +1553,8 @@ int cmd_stash(int argc, const char **argv, const char *prefix)\n \tstruct argv_array args = ARGV_ARRAY_INIT;\n\n \tstruct option options[] = {\n+\t\tOPT_STRING('r', \"ref\", &ref_stash, N_(\"ref\"),\n+\t\t\t   N_(\"override `refs/stash`\")),\n \t\tOPT_END()\n \t};\n\n-- snap --\n\nThe biggest trick will be to make all the code paths safe that assume\nthat `ref_stash` refers to a valid ref ;-)\n\nCiao,\nDscho\n"},{"id":"385220","messageId":"20191031134034.GA63909@cat","threadId":"52127","inReplyTo":"nycvar.QRO.7.76.6.1910290806310.46@tvgsbejvaqbjf.bet","subject":"Re: [FR] Allow `git stash create` to include untracked changes","fromName":"Thomas Gummerer","fromEmail":"t.gummerer@gmail.com","sentAt":"2019-10-31T13:40:34Z","receivedAt":"2019-10-31T13:40:39Z","isPatch":false,"sender":{"key":"t.gummerer@gmail.com","avatar":"https://avatars.githubusercontent.com/u/191004?v=4"},"body":"On 10/29, Johannes Schindelin wrote:\n> So why does `git stash create -u ...` not work? Because the original\n> design of `git stash create` never intended to take any command-line\n> arguments other than the stash message. And that design can obviously\n> not be fixed without breaking backwards compatibility.\n\nYup that's exactly right.  Not breaking this sort of backwards\ncompatibility is also why we have both 'git stash save' and 'git stash\npush' nowadays.\n\nWe did have a similar conversation back when 'git stash push' was\nintroduced [1].  We almost decided this regression would be okay, but\nin the end went with calling 'create_stash -m \"$*\"' internally to\ncircumvent the problem.  Now that somebody has an actual usecase we\nmay or may not find this \"regression\" acceptable.  I don't have a\nstrong opinion about it, so this is just to add a little bit of\ncontext here.\n\n[1]: https://public-inbox.org/git/20170206155606.xgkmhg656vuc6uki@sigill.intra.peff.net/\n\n> What we _could_ do is to add a new command-line option to `git stash\n> push` that would make it behave like the `create` subsubcommand: _not_\n> update the `refs/stash` ref but instead print the commit hash.\n> \n> I am not quite sure how to call this option (`--ephemeral` came to my\n> mind, as the created commit is not reachable from anywhere and is hence\n> subject to garbage collection).\n> \n> A completely different approach would be to allow overriding the ref to\n> store the stash in, with an empty value triggering the mode where the\n> ref is not updated but the commit hash would be printed instead. I am\n> thinking of something like `git stash -r '' push ...`, starting with\n> this patch:\n> \n> -- snip --\n> diff --git a/builtin/stash.c b/builtin/stash.c\n> index bb4f6d8d762..43b0a155b1d 100644\n> --- a/builtin/stash.c\n> +++ b/builtin/stash.c\n> @@ -1553,6 +1553,8 @@ int cmd_stash(int argc, const char **argv, const char *prefix)\n>  \tstruct argv_array args = ARGV_ARRAY_INIT;\n> \n>  \tstruct option options[] = {\n> +\t\tOPT_STRING('r', \"ref\", &ref_stash, N_(\"ref\"),\n> +\t\t\t   N_(\"override `refs/stash`\")),\n>  \t\tOPT_END()\n>  \t};\n> \n> -- snap --\n> \n> The biggest trick will be to make all the code paths safe that assume\n> that `ref_stash` refers to a valid ref ;-)\n> \n> Ciao,\n> Dscho\n"}]}