Git development
 help / color / mirror / Atom feed
* git submodule update  strange output behavior.
From: Carlo Wood @ 2020-01-09 18:20 UTC (permalink / raw)
  To: git


In a project containing submodules, one of the submodules
contains a submodule itself, which in turn also contains
a submodule.

Overview:

project/foobar  [submodule]
project/cwm4    [submodule]
project/evio    [submodule]
project/evio/protocol/matrixssl       [submodule]
project/evio/protocol/matrixssl/cwm4  [submodule]

('protocol' is a normal subdirectory)

Running (with or without the --quiet),

$ git submodule --quiet update --init --recursive --remote
Fetching submodule protocol/matrixssl
Fetching submodule protocol/matrixssl/cwm4
Fetching submodule cwm4

This is odd (a bug imho) because

1) it seems to only print this fetching information for submodules inside submodules,
not for the top-level submodules.
2) it even prints this when using --quiet
3) it prints this every time (also when there is nothing more to fetch).

-- 
Carlo Wood <carlo@alinoe.com>

^ permalink raw reply

* Re: Unreliable 'git rebase --onto'
From: Elijah Newren @ 2020-01-09 18:05 UTC (permalink / raw)
  To: Eugeniu Rosca
  Cc: SZEDER Gábor, Junio C Hamano, Jeff King,
	Ævar Arnfjörð, Git Mailing List, Eugeniu Rosca
In-Reply-To: <20200109105307.GA1349@lxhi-065.adit-jv.com>

On Thu, Jan 9, 2020 at 2:53 AM Eugeniu Rosca <erosca@de.adit-jv.com> wrote:
>
> Hi Elijah, hi Szeder,
>
> On Wed, Jan 08, 2020 at 02:06:22PM -0800, Elijah Newren wrote:
> > This looks like a known bug in rebase, in particular in the am-backend that
> > rebase uses by default.  If I'm correct that it's just a context region
> > issue, then this is the same bug that was recently discussed at
> > https://lore.kernel.org/git/CAN_72e2h2avv-U9BVBYqXVKiC+5kHy-pjejyMSD3X22uRXE39g@mail.gmail.com/.
> > The current plan is to switch the default over to the merge backend (the
> > same machinery that cherry-pick uses), which doesn't suffer from the same
> > shortcomings (you can see the current work being done in this area at
> > https://lore.kernel.org/git/pull.679.v3.git.git.1577217299.gitgitgadget@gmail.com/
> > ).
>
> Thank you for your feedback and references, here and in [*].
>
> Once hit by this or similar issues, I think there is high chance for
> people to go through the same feelings as described by Pavel in [**]:
>
>   ---
>   That's so scary that I'm going to stop using "git rebase" for now.
>   ---

Yep, I understand; that kind of feeling is why I wanted to jump in and
try to help fix it.  I want merge/rebase/cherry-pick to be reliable.

> Some years ago I was hit by 'git merge' producing slightly different
> results compared to 'git rebase --onto' and 'git cherry-pick A..B'
> (maybe I can come up with a reproduction scenario for that too).

If you can, I'd be interested to see it and take a look.  I'd normally
assume it was just some case where A..B included "evil" merge commits
(merge commits that made additional changes not part of the actual
merging) since rebasing or cherry-picking such a range would exclude
the merge commits and thus drop those changes -- but you identified a
real bug with the default rebase backend so I'm interested to see if
you happen to have more bugs I should know about.

>
> Since then, I usually contrast the outcomes of merging, cherry-picking
> and rebasing, to make sure they match, but that's painful and
> time-consuming.
>
> > In the mean time, you can pass the -m flag to rebase to avoid these types
> > of problems.  In fact, if you could retry with -m you may be able to
> > confirm whether it's the same issue.
>
> Indeed, neither `git rebase -m` nor `git rebase -i` exhibit the problem.

That's good news.

Unfortunately, you should note that git-2.25 is going to have the same
bug you reported; there are still some loose ends with my series to
make -m the default, and the 2.25 release is expected within a few
days, so my change of default won't happen until 2.26.  (That series
would have needed to be completed several weeks ago for it to go into
2.25).

^ permalink raw reply

* Re: Unreliable 'git rebase --onto'
From: Elijah Newren @ 2020-01-09 17:53 UTC (permalink / raw)
  To: SZEDER Gábor
  Cc: Eugeniu Rosca, Junio C Hamano, Jeff King,
	Ævar Arnfjörð, Git Mailing List, Eugeniu Rosca
In-Reply-To: <20200109150332.GF32750@szeder.dev>

Hi,

On Thu, Jan 9, 2020 at 7:03 AM SZEDER Gábor <szeder.dev@gmail.com> wrote:
>
> On Wed, Jan 08, 2020 at 04:55:46PM -0800, Elijah Newren wrote:
> > > Alas, there is unexpected bad news: with that commit the runtime of
> > > your 'git rebase --onto' command goes from <1sec to over 50secs.
> > > Cc-ing Elijah, author of that patch...
> >
> > I see slowdown, but not nearly as big as you report:
>
> The linux repo is big, my notebook is small, the poor thing :)

It went to just over 64secs on my home laptop (older and with spinny
disks), so yeah, a big difference from my work machine which has an
SSD.

> > $ time git rebase -m --onto v4.18 463fa44eec2fef50~ 463fa44eec2fef50
> > warning: inexact rename detection was skipped due to too many files.
> > warning: you may want to set your merge.renamelimit variable to at
> > least 7216 and retry the command.
> > Successfully rebased and updated detached HEAD.
> >
> > real 0m13.305s
> > user 0m9.644s
> > sys 0m3.620s
>
> > Interestingly, turning off rename detection only speeds it up a little bit:
> > $ time git rebase -m -Xno-renames --onto v4.18 463fa44eec2fef50~
> > 463fa44eec2fef50
> > Successfully rebased and updated detached HEAD.
> >
> > real 0m11.955s
> > user 0m8.732s
> > sys 0m3.424s
> >
> >
> > This is an interesting testcase; I'm going to try to find some time to
> > dig in further.
>
> The culprits are two seemingly unnecessary back-and-forth checkouts.
>
> I didn't realize I could use 'git rebase -m', so ran some tests with
> it, and turns out that the slowdown started with 68aa495b59 (rebase:
> implement --merge via the interactive machinery, 2018-12-11), where
> the runtime suddenly went from <1.5s to 45+s.
>
> Running 'git rebase -i --onto <those-same-commits>' is just as slow,
> and it appears that it has always been (the oldest I tried was
> v1.8.0), and it spends a long time both before and after popping up
> the editor for the rebase instructions.  That's highly suspicious, so:
>
>   $ git log --oneline -1
>   94710cac0ef4 (HEAD, tag: v4.18) Linux 4.18
>   $ git rebase -i --onto v4.18 463fa44eec2fef50~ 463fa44eec2fef50
>   hint: Waiting for your editor to close the file...
>   # Hit ctrl-z in the editor
>   $ git log --oneline -1
>   463fa44eec2f (HEAD) Input: atmel_mxt_ts - disable IRQ across suspend
>
> Oh.
>
> So 'git rebase -i' apparently checks out the tip commit of the
> to-be-rebased revision range before invoking the editor for the rebase
> instructions, only to check out the --onto commit (i.e. the commit
> we've started from!) to apply the selected commit on top.
>
> And indeed those two checkouts account for all the wasted runtime:
>
>   $ time { git checkout 463fa44eec2fef50 && git checkout v4.18 ; }
>   Updating files: 100% (49483/49483), done.
>   Previous HEAD position was 94710cac0ef4 Linux 4.18
>   HEAD is now at 463fa44eec2f Input: atmel_mxt_ts - disable IRQ across suspend
>   Updating files: 100% (49483/49483), done.
>   Previous HEAD position was 463fa44eec2f Input: atmel_mxt_ts - disable IRQ across suspend
>   HEAD is now at 94710cac0ef4 Linux 4.18
>
>   real    0m48.801s
>   user    0m13.963s
>   sys     0m5.114s

Oh, cool, sounds like you're already investigating and found the problem.

^ permalink raw reply

* Bug report: 'git svn fetch' failing during parent resolution
From: Miller, Robert @ 2020-01-09 16:28 UTC (permalink / raw)
  To: 'git@vger.kernel.org'

Hello all,

While I've been working on migrating my team's SVN repository into Git, I've run into what I believe to be a bug in git-svn's fetching functionality. In particular, I'm getting output which looks like this (with the repo URL redacted):

$ git svn fetch
branch_from: /Projects/WORMS/Database_Schemas/TradeDb => /Projects/WORMS/Database_Schemas/TradeDb/tags/v12/0.12.26.0
Found possible branch point: [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb/tags/v12/0.12.26.0 => [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb_Daily/tags/v12/0.12.26.0, 68307
Initializing parent: refs/remotes/origin/tags/0.12.26.0@68307
Found possible branch point: [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb/tags/0.12.26.0 => [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb/tags/v12/0.12.26.0, 56925
Initializing parent: refs/remotes/origin/tags/0.12.26.0@56925
Found possible branch point: [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb/trunk/WormsModelDb.bak => [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb/tags/0.12.26.0, 54810
Initializing parent: refs/remotes/origin/tags/0.12.26.0@54810
Found possible branch point: [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb/WormsModelDb.bak => [SVN_URL]/Projects/WORMS/Database_Schemas/TradeDb/trunk/WormsModelDb.bak, 46608
Initializing parent: refs/remotes/origin/tags/0.12.26.0@46608
Use of uninitialized value $args[1] in join or string at C:/Program Files/Git/mingw64/share/perl5/Git.pm line 1635.
Use of uninitialized value $_[2] in exec at C:/Program Files/Git/mingw64/share/perl5/Git.pm line 1661.
fatal: Not a valid object name
ls-tree -z  ./: command returned error: 128

This output is from Git version 2.24.1.windows.2 running on Windows 10 1903 and accessing an SVN repository which is, to the best of my knowledge, on version 1.9.5 (I don't have direct access to the server SVN is hosted on to check its version myself; I can follow up if the specific SVN version turns out to be relevant to the investigation). The fetch operation had been running smoothly up until I hit this error case, but now every invocation of 'git svn fetch' produces this same output.

Based on the generated output (and my very limited knowledge of Git's codebase and Perl's syntax), I believe that the problem stems from the following:
1) Within either Git::SVN::Fetcher's delete_entry or open_file function (I'm not sure exactly which, but the "ls-tree -z  ./" construction appears to only come from one of those two places), the value $self->{c} is undefined
2) $self->{c} is only set in Fetcher's constructor, where it takes the value $git_svn->{last_commit}, implying that this value is also undefined
3) This value would have been set during a call to Git::SVN's find_parent_branch function if a call to find_rev_before had returned defined values

My theory, then, is that git-svn failed to find a valid parent revision, but doesn't have error-handling logic in place to handle this edge case when the SVN repository has orphaned revisions that appear to be related to the tag being processed. This would be in keeping with the behavior reported in a Stack Overflow question from 2010 (https://stackoverflow.com/questions/4367460/git-svn-fetch-fails-ls-tree-dying-because-of-missing-tree-object) featuring very similar output to what I ended up seeing.

In my case, I believe that the issue stems from the non-standard repository structure (with the 'tags' directory containing subdirectories rather than directly containing tags). The tag named '0.12.26.0' was originally created at the base level of the 'tags' directory, but later moved into the 'v12' subdirectory;  it's possible that this move was somehow botched and resulted in a repository structure that git-svn isn't able to make sense of.

Assuming that my analysis is correct (and since I'm somewhat out of my depth here, it very well may not be), I would propose some combination of hardening the Fetcher against missing data, providing some sort of diagnostic warning/error message, and/or discarding orphaned SVN commits without passing them to the Fetcher to begin with, perhaps controlled by some additional switch for the fetch command.

If there's any other information I can provide that would be helpful for investigating this issue, let me know and I'll be happy to provide it.

Thanks,
Robert Miller
 
------------------------------------------------------------------------------

This message is intended only for the personal and confidential use of the recipients named above. If the reader of this email is not the intended recipient, you have received this email in error and any review, dissemination, distribution or copying is strictly prohibited. If you have received this email in error, please notify the sender immediately by return email and permanently delete the copy you received.

This message is provided for informational purposes and should not be construed as a solicitation or offer to buy or sell any securities or related financial instruments. Wolverine is not responsible for any recommendation, solicitation, offer or agreement or any information about any transaction, customer account or account activity that may be attached to or contained in this communication. Wolverine accepts no liability for any content contained in the email, or any errors or omissions arising as a result of e-mail transmission. Any opinions contained in this email constitute the sender's best judgment at this time and are subject to change without notice.


^ permalink raw reply

* Re: Unreliable 'git rebase --onto'
From: SZEDER Gábor @ 2020-01-09 15:03 UTC (permalink / raw)
  To: Elijah Newren
  Cc: Eugeniu Rosca, Junio C Hamano, Jeff King,
	Ævar Arnfjörð, Git Mailing List, Eugeniu Rosca
In-Reply-To: <CABPp-BHsy75UGm4wTOP2_AYik_dZi-_BxtAn-hyi-ZrNRRWGuw@mail.gmail.com>

On Wed, Jan 08, 2020 at 04:55:46PM -0800, Elijah Newren wrote:
> > Alas, there is unexpected bad news: with that commit the runtime of
> > your 'git rebase --onto' command goes from <1sec to over 50secs.
> > Cc-ing Elijah, author of that patch...
> 
> I see slowdown, but not nearly as big as you report:

The linux repo is big, my notebook is small, the poor thing :)

> $ time git rebase -m --onto v4.18 463fa44eec2fef50~ 463fa44eec2fef50
> warning: inexact rename detection was skipped due to too many files.
> warning: you may want to set your merge.renamelimit variable to at
> least 7216 and retry the command.
> Successfully rebased and updated detached HEAD.
> 
> real 0m13.305s
> user 0m9.644s
> sys 0m3.620s

> Interestingly, turning off rename detection only speeds it up a little bit:
> $ time git rebase -m -Xno-renames --onto v4.18 463fa44eec2fef50~
> 463fa44eec2fef50
> Successfully rebased and updated detached HEAD.
> 
> real 0m11.955s
> user 0m8.732s
> sys 0m3.424s
> 
> 
> This is an interesting testcase; I'm going to try to find some time to
> dig in further.

The culprits are two seemingly unnecessary back-and-forth checkouts.

I didn't realize I could use 'git rebase -m', so ran some tests with
it, and turns out that the slowdown started with 68aa495b59 (rebase:
implement --merge via the interactive machinery, 2018-12-11), where
the runtime suddenly went from <1.5s to 45+s.

Running 'git rebase -i --onto <those-same-commits>' is just as slow,
and it appears that it has always been (the oldest I tried was
v1.8.0), and it spends a long time both before and after popping up
the editor for the rebase instructions.  That's highly suspicious, so:

  $ git log --oneline -1
  94710cac0ef4 (HEAD, tag: v4.18) Linux 4.18
  $ git rebase -i --onto v4.18 463fa44eec2fef50~ 463fa44eec2fef50
  hint: Waiting for your editor to close the file... 
  # Hit ctrl-z in the editor
  $ git log --oneline -1
  463fa44eec2f (HEAD) Input: atmel_mxt_ts - disable IRQ across suspend

Oh.

So 'git rebase -i' apparently checks out the tip commit of the
to-be-rebased revision range before invoking the editor for the rebase
instructions, only to check out the --onto commit (i.e. the commit
we've started from!) to apply the selected commit on top.

And indeed those two checkouts account for all the wasted runtime:

  $ time { git checkout 463fa44eec2fef50 && git checkout v4.18 ; }
  Updating files: 100% (49483/49483), done.
  Previous HEAD position was 94710cac0ef4 Linux 4.18
  HEAD is now at 463fa44eec2f Input: atmel_mxt_ts - disable IRQ across suspend
  Updating files: 100% (49483/49483), done.
  Previous HEAD position was 463fa44eec2f Input: atmel_mxt_ts - disable IRQ across suspend
  HEAD is now at 94710cac0ef4 Linux 4.18
  
  real    0m48.801s
  user    0m13.963s
  sys     0m5.114s


^ permalink raw reply

* [PATCH] mingw: safeguard better against backslashes in file names
From: Johannes Schindelin via GitGitGadget @ 2020-01-09 13:30 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin

In 224c7d70fa1 (mingw: only test index entries for backslashes, not tree
entries, 2019-12-31), we relaxed the check for backslashes in tree
entries to check only index entries.

However, the code change was incorrect: it was added to
`add_index_entry_with_check()`, not to `add_index_entry()`, so under
certain circumstances it was possible to side-step the protection.

Besides, the description of that commit purported that all index entries
would be checked when in fact they were only checked when being added to
the index (there are code paths that do not do that, constructing
"transient" index entries).

In any case, it was pointed out in one insightful review at
https://github.com/git-for-windows/git/pull/2437#issuecomment-566771835
that it would be a much better idea to teach `verify_path()` to perform
the check for a backslash. This is safer, even if it comes with two
notable drawbacks:

- `verify_path()` cannot say _what_ is wrong with the path, therefore
  the user will no longer be told that there was a backslash in the
  path, only that the path was invalid.

- The `git apply` command also calls the `verify_path()` function, and
  might have been able to handle Windows-style paths (i.e. with
  backslashes instead of forward slashes). This will no longer be
  possible unless the user (temporarily) sets `core.protectNTFS=false`.

Note that `git add <windows-path>` will _still_ work because
`normalize_path_copy_len()` will convert the backslashes to forward
slashes before hitting the code path that creates an index entry.

The clear advantage is that `verify_path()`'s purpose is to check the
validity of the file name, therefore we naturally tap into all the code
paths that need safeguarding, also implicitly into future code paths.

The benefits of that approach outweigh the downsides, so let's move the
check from `add_index_entry_with_check()` to `verify_path()`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
    mingw: safeguard better against backslashes in file names
    
    I investigated again, and I think that there are code paths involving 
    make_transient_cache_entry() that might be vulnerable again after my
    recent change in 224c7d70fa1 (mingw: only test index entries for
    backslashes, not tree entries, 2019-12-31).
    
    This version should help with keeping Git for Windows' users safe.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-690%2Fdscho%2Fonly-error-on-backslash-in-index-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-690/dscho/only-error-on-backslash-in-index-v1
Pull-Request: https://github.com/git/git/pull/690

 read-cache.c               | 12 ++++++------
 t/t7415-submodule-names.sh |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/read-cache.c b/read-cache.c
index 737916ebd9..aa427c5c17 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -959,7 +959,7 @@ static int verify_dotfile(const char *rest, unsigned mode)
 
 int verify_path(const char *path, unsigned mode)
 {
-	char c;
+	char c = 0;
 
 	if (has_dos_drive_prefix(path))
 		return 0;
@@ -974,6 +974,7 @@ int verify_path(const char *path, unsigned mode)
 		if (is_dir_sep(c)) {
 inside:
 			if (protect_hfs) {
+
 				if (is_hfs_dotgit(path))
 					return 0;
 				if (S_ISLNK(mode)) {
@@ -982,6 +983,10 @@ int verify_path(const char *path, unsigned mode)
 				}
 			}
 			if (protect_ntfs) {
+#ifdef GIT_WINDOWS_NATIVE
+				if (c == '\\')
+					return 0;
+#endif
 				if (is_ntfs_dotgit(path))
 					return 0;
 				if (S_ISLNK(mode)) {
@@ -1278,11 +1283,6 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 	int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
 	int new_only = option & ADD_CACHE_NEW_ONLY;
 
-#ifdef GIT_WINDOWS_NATIVE
-	if (protect_ntfs && strchr(ce->name, '\\'))
-		return error(_("filename in tree entry contains backslash: '%s'"), ce->name);
-#endif
-
 	if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
 		cache_tree_invalidate_path(istate, ce->name);
 
diff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh
index 7ae0dc8ff4..f70368bc2e 100755
--- a/t/t7415-submodule-names.sh
+++ b/t/t7415-submodule-names.sh
@@ -209,7 +209,7 @@ test_expect_success MINGW 'prevent git~1 squatting on Windows' '
 		hash="$(echo x | git hash-object -w --stdin)" &&
 		test_must_fail git update-index --add \
 			--cacheinfo 160000,$rev,d\\a 2>err &&
-		test_i18ngrep backslash err &&
+		test_i18ngrep "Invalid path" err &&
 		git -c core.protectNTFS=false update-index --add \
 			--cacheinfo 100644,$modules,.gitmodules \
 			--cacheinfo 160000,$rev,c \

base-commit: 7a6a90c6ec48fc78c83d7090d6c1b95d8f3739c0
-- 
gitgitgadget

^ permalink raw reply related

* Re: Unreliable 'git rebase --onto'
From: Eugeniu Rosca @ 2020-01-09 11:13 UTC (permalink / raw)
  To: SZEDER Gábor
  Cc: Eugeniu Rosca, Elijah Newren, gitster, peff, avarab, git,
	Eugeniu Rosca
In-Reply-To: <20200108223557.GE32750@szeder.dev>

Hi Szeder,

On Wed, Jan 08, 2020 at 11:35:57PM +0100, SZEDER Gábor wrote:
> This is a known issue with the 'am' backend of 'git rebase'.
> 
> The good news is that work is already well under way to change the
> default backend from 'am' to 'merge', which will solve this issue.
> From the log message of aa523de170 (rebase: change the default backend
> from "am" to "merge", 2019-12-24):
> 
>   The am-backend drops information and thus limits what we can do:
>   [...]
>     * reduction in context from only having a few lines beyond those
>       changed means that when context lines are non-unique we can apply
>       patches incorrectly.[2]
>   [...]
>   [2] https://lore.kernel.org/git/CABPp-BGiu2nVMQY_t-rnFR5GQUz_ipyEE8oDocKeO+>
> 
> Alas, there is unexpected bad news: with that commit the runtime of
> your 'git rebase --onto' command goes from <1sec to over 50secs.
> Cc-ing Elijah, author of that patch...

[$.02] I would personally take the route of regaining users' trust in
'git rebase' first, with fixing the performance penalty later on.

I was quite impressed by the recent 2.24.0 performance improvements,
which tells there might be room for improvement for `git rebase` too,
once it is fixed.

-- 
Best Regards,
Eugeniu

^ permalink raw reply

* Re: Unreliable 'git rebase --onto'
From: Eugeniu Rosca @ 2020-01-09 10:53 UTC (permalink / raw)
  To: Elijah Newren, SZEDER Gábor
  Cc: Eugeniu Rosca, Junio C Hamano, Jeff King,
	Ævar Arnfjörð, Git Mailing List, Eugeniu Rosca
In-Reply-To: <CABPp-BHsyMOz+hi7EYoAnAWfzms7FRfwqCoarnu8H+vyDoN6SQ@mail.gmail.com>

Hi Elijah, hi Szeder,

On Wed, Jan 08, 2020 at 02:06:22PM -0800, Elijah Newren wrote:
> This looks like a known bug in rebase, in particular in the am-backend that
> rebase uses by default.  If I'm correct that it's just a context region
> issue, then this is the same bug that was recently discussed at
> https://lore.kernel.org/git/CAN_72e2h2avv-U9BVBYqXVKiC+5kHy-pjejyMSD3X22uRXE39g@mail.gmail.com/.
> The current plan is to switch the default over to the merge backend (the
> same machinery that cherry-pick uses), which doesn't suffer from the same
> shortcomings (you can see the current work being done in this area at
> https://lore.kernel.org/git/pull.679.v3.git.git.1577217299.gitgitgadget@gmail.com/
> ).

Thank you for your feedback and references, here and in [*].

Once hit by this or similar issues, I think there is high chance for
people to go through the same feelings as described by Pavel in [**]:

  ---
  That's so scary that I'm going to stop using "git rebase" for now.
  ---

Some years ago I was hit by 'git merge' producing slightly different
results compared to 'git rebase --onto' and 'git cherry-pick A..B'
(maybe I can come up with a reproduction scenario for that too).

Since then, I usually contrast the outcomes of merging, cherry-picking
and rebasing, to make sure they match, but that's painful and
time-consuming.

> In the mean time, you can pass the -m flag to rebase to avoid these types
> of problems.  In fact, if you could retry with -m you may be able to
> confirm whether it's the same issue.

Indeed, neither `git rebase -m` nor `git rebase -i` exhibit the problem.

[*] https://lore.kernel.org/git/CABPp-BHsy75UGm4wTOP2_AYik_dZi-_BxtAn-hyi-ZrNRRWGuw@mail.gmail.com/T/#m1cbf80ef56c260a626146d61291d7fbabd108f1b
[**] https://lore.kernel.org/git/CAN_72e2h2avv-U9BVBYqXVKiC+5kHy-pjejyMSD3X22uRXE39g@mail.gmail.com/

Thanks again.

-- 
Best Regards,
Eugeniu

^ permalink raw reply

* Re: Broken branch after git commit - tracked files in staging area can't be removed with restore --staged, or commit or stash
From: Torsten Krah @ 2020-01-09 10:49 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20200109093931.GA299671@coredump.intra.peff.net>

Am Donnerstag, den 09.01.2020, 04:39 -0500 schrieb Jeff King:
> You should be able to do:
> 
>   git checkout your-branch
>   git reset --hard <original>
> 
> to go back to the state you were at (this is assuming you haven't
> built
> more commits on top, of course), and then repeat your steps. That
> should
> also clear out any breakage in the index, since "reset --hard" will
> invalidate the cache-tree as necessary.
> 
> If you need to find the commit id of that original commit, try
> looking
> in the reflog for your branch: git log -g your-branch

Hi Peff,

thanks that did work - but I had to "rm .git/index" before the hard
reset to get those "deleted" ones removed from the staging area, after
that I was able to use "git reset -- $files" and that was working like
expected.
Without deleting that index file I could run the hard reset but running
"git status" afterwards insisted every time on this:

On branch feature-2182
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    docker-compose.gerrit.yml
	deleted:    docker-compose.reverseproxy.yml
	deleted:    docker-compose.yml
	deleted:    docker-seccomp.json
	deleted:    gradle.properties
	deleted:    settings.gradle

Those only vanished after deleting the index file.

The "settings.gradle" is part of my changeset and listed in the
"commit".
But those other 5 files listed I had never touched in my commit - I
don't know why they are in the staging area here - maybe some other
edge case of the git restore bug - but just a "git hard --reset $hash"
did not clear those.

Torsten
-- 



^ permalink raw reply

* [PATCH v2 4/4] config: add '--show-scope' to print the scope of a config value
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers
In-Reply-To: <pull.478.v2.git.1578565001.gitgitgadget@gmail.com>

From: Matthew Rogers <mattr94@gmail.com>

When a user queries config values with --show-origin, often it's
difficult to determine what the actual "scope" (local, global, etc.) of
a given value is based on just the origin file.

Teach 'git config' the '--show-scope' option to print the scope of all
displayed config values.  Note that we should never see anything of
"submodule" scope as that is only ever used by submodule-config.c when
parsing the '.gitmodules' file.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 Documentation/git-config.txt | 15 ++++++----
 builtin/config.c             | 56 ++++++++++++++++++++++++++++++++----
 config.c                     |  6 +++-
 config.h                     | 20 +++++++------
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       |  4 ++-
 t/t1300-config.sh            | 50 ++++++++++++++++++++++++++++++++
 7 files changed, 133 insertions(+), 22 deletions(-)

diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 899e92a1c9..2e47765aab 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,18 +9,18 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
 'git config' [<file-option>] [--type=<type>] --add name value
 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
 'git config' [<file-option>] --unset name [value_regex]
 'git config' [<file-option>] --unset-all name [value_regex]
 'git config' [<file-option>] --rename-section old_name new_name
 'git config' [<file-option>] --remove-section name
-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
+'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list
 'git config' [<file-option>] --get-color name [default]
 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
 'git config' [<file-option>] -e | --edit
@@ -222,6 +222,11 @@ Valid `<type>`'s include:
 	the actual origin (config file path, ref, or blob id if
 	applicable).
 
+--show-scope::
+	Similar to `--show-origin` in that it augments the output of
+	all queried config options with the scope of that value 
+	(local, global, system, command).
+
 --get-colorbool name [stdout-is-tty]::
 
 	Find the color setting for `name` (e.g. `color.diff`) and output
diff --git a/builtin/config.c b/builtin/config.c
index 52a904cfb1..0367d28ec1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -33,6 +33,7 @@ static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
+static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -155,6 +156,7 @@ static struct option builtin_config_options[] = {
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -189,11 +191,41 @@ static void show_config_origin(struct strbuf *buf)
 	strbuf_addch(buf, term);
 }
 
+static const char *scope_to_string(enum config_scope scope) {
+	switch (scope) {
+	case CONFIG_SCOPE_LOCAL:
+		return "local";
+	case CONFIG_SCOPE_GLOBAL:
+		return "global";
+	case CONFIG_SCOPE_SYSTEM:
+		return "system";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
+	default:
+		return "unknown";
+	}
+}
+
+static void show_config_scope(struct strbuf *buf) {
+	const char term = end_nul ? '\0' : '\t';
+	const char *scope = scope_to_string(current_config_scope());
+
+	strbuf_addstr(buf, N_(scope));
+	strbuf_addch(buf, term);
+}
+
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin) {
+	if (show_origin || show_scope) {
 		struct strbuf buf = STRBUF_INIT;
-		show_config_origin(&buf);
+		if (show_scope)
+			show_config_scope(&buf);
+		if (show_origin)
+			show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -213,6 +245,8 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
+	if (show_scope)
+		show_config_origin(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -599,6 +633,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 	int nongit = !startup_info->have_repository;
 	char *value;
 
+
+
 	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
 
 	argc = parse_options(argc, argv, prefix, builtin_config_options,
@@ -622,6 +658,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -637,6 +674,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
+		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
+
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -646,11 +685,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config)
+	else if (use_system_config) {
 		given_config_source.file = git_etc_gitconfig();
-	else if (use_local_config)
+		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
+	} else if (use_local_config) {
 		given_config_source.file = git_pathdup("config");
-	else if (use_worktree_config) {
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
+	} else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -662,13 +703,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
+		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
+	} else if (given_config_source.blob) {
+		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
+
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
diff --git a/config.c b/config.c
index f319a3d6a0..035fc8fb29 100644
--- a/config.c
+++ b/config.c
@@ -1702,6 +1702,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	char *xdg_config = xdg_config_home("config");
 	char *user_config = expand_user_path("~/.gitconfig", 0);
 	char *repo_config;
+	enum config_scope prev_parsing_scope = current_parsing_scope;
 
 	if (opts->commondir)
 		repo_config = mkpathdup("%s/config", opts->commondir);
@@ -1741,7 +1742,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
+	current_parsing_scope = prev_parsing_scope;
 	free(xdg_config);
 	free(user_config);
 	free(repo_config);
@@ -1762,6 +1763,9 @@ int config_with_options(config_fn_t fn, void *data,
 		data = &inc;
 	}
 
+	if (config_source)
+		current_parsing_scope = config_source->scope;
+
 	/*
 	 * If we have a specific filename, use it. Otherwise, follow the
 	 * regular lookup sequence.
diff --git a/config.h b/config.h
index f383a71404..91f851e925 100644
--- a/config.h
+++ b/config.h
@@ -35,10 +35,21 @@ struct object_id;
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+enum config_scope {
+	CONFIG_SCOPE_UNKNOWN = 0,
+	CONFIG_SCOPE_SYSTEM,
+	CONFIG_SCOPE_GLOBAL,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
+	CONFIG_SCOPE_COMMAND,
+	CONFIG_SCOPE_SUBMODULE,
+};
+
 struct git_config_source {
 	unsigned int use_stdin:1;
 	const char *file;
 	const char *blob;
+	enum config_scope scope;
 };
 
 enum config_origin_type {
@@ -294,15 +305,6 @@ int config_error_nonbool(const char *);
 
 int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
-enum config_scope {
-	CONFIG_SCOPE_UNKNOWN = 0,
-	CONFIG_SCOPE_SYSTEM,
-	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_LOCAL,
-	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_COMMAND,
-};
-
 enum config_scope current_config_scope(void);
 const char *current_config_origin_type(void);
 const char *current_config_name(void);
diff --git a/submodule-config.c b/submodule-config.c
index 85064810b2..b8e97d8ae8 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -635,7 +635,9 @@ static void submodule_cache_check_init(struct repository *repo)
 static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
 {
 	if (repo->worktree) {
-		struct git_config_source config_source = { 0 };
+		struct git_config_source config_source = {
+			0, .scope = CONFIG_SCOPE_SUBMODULE
+		};
 		const struct config_options opts = { 0 };
 		struct object_id oid;
 		char *file;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 78bbb9eb98..aae2c6fc9e 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,10 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
+	case CONFIG_SCOPE_SUBMODULE:
+		return "submodule";
 	case CONFIG_SCOPE_COMMAND:
-		return "command";
+		return "cmdline";
 	default:
 		return "unknown";
 	}
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 983a0a1583..6cecc80b18 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -1766,6 +1766,56 @@ test_expect_success !MINGW '--show-origin blob ref' '
 	test_cmp expect output
 '
 
+test_expect_success '--show-scope with --list' '
+	cat >expect <<-EOF &&
+		global	user.global=true
+		global	user.override=global
+		global	include.path=$INCLUDE_DIR/absolute.include
+		global	user.absolute=include
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+		local	user.relative=include
+		command	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success !MINGW '--show-scope with --blob' '
+	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
+	cat >expect <<-EOF &&
+		command	user.custom=true
+	EOF
+	git config --blob=$blob --show-scope --list >output &&
+	test_cmp expect output
+'
+test_expect_success '--show-scope with --local' '
+	cat >expect <<-\EOF &&
+		local	user.local=true
+		local	user.override=local
+		local	include.path=../include/relative.include
+	EOF
+	git config --local --list --show-scope >output &&
+	test_cmp expect output
+'
+
+test_expect_success '--show-scope with --show-origin' '
+	cat >expect <<-EOF &&
+		global	file:$HOME/.gitconfig	user.global=true
+		global	file:$HOME/.gitconfig	user.override=global
+		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
+		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
+		local	file:.git/config	user.local=true
+		local	file:.git/config	user.override=local
+		local	file:.git/config	include.path=../include/relative.include
+		local	file:.git/../include/relative.include	user.relative=include
+		command	command line:	user.cmdline=true
+	EOF
+	git -c user.cmdline=true config --list --show-origin --show-scope >output &&
+	test_cmp expect output
+'
+
 test_expect_success '--local requires a repo' '
 	# we expect 128 to ensure that we do not simply
 	# fail to find anything and return code "1"
-- 
gitgitgadget

^ permalink raw reply related

* [PATCH v2 3/4] config: clarify meaning of command line scoping
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers
In-Reply-To: <pull.478.v2.git.1578565001.gitgitgadget@gmail.com>

From: Matthew Rogers <mattr94@gmail.com>

CONFIG_SCOPE_CMDLINE is generally used in the code to refer to config
values passed in via the -c option.  This is a little bit too specific
as there are other methods to pass config values so that the last for a
single command (namely --file and --blob).  As the "visibility" of config
values passed by these situations is common, we unify them as having a
scope of "command" rather than "command line".

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 2 +-
 config.h               | 2 +-
 t/helper/test-config.c | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/config.c b/config.c
index 447a013a15..f319a3d6a0 100644
--- a/config.c
+++ b/config.c
@@ -1737,7 +1737,7 @@ static int do_git_config_sequence(const struct config_options *opts,
 		free(path);
 	}
 
-	current_parsing_scope = CONFIG_SCOPE_CMDLINE;
+	current_parsing_scope = CONFIG_SCOPE_COMMAND;
 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
 		die(_("unable to parse command-line config"));
 
diff --git a/config.h b/config.h
index 284d92fb0e..f383a71404 100644
--- a/config.h
+++ b/config.h
@@ -300,7 +300,7 @@ enum config_scope {
 	CONFIG_SCOPE_GLOBAL,
 	CONFIG_SCOPE_LOCAL,
 	CONFIG_SCOPE_WORKTREE,
-	CONFIG_SCOPE_CMDLINE,
+	CONFIG_SCOPE_COMMAND,
 };
 
 enum config_scope current_config_scope(void);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 6695e463eb..78bbb9eb98 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -48,8 +48,8 @@ static const char *scope_name(enum config_scope scope)
 		return "repo";
 	case CONFIG_SCOPE_WORKTREE:
 		return "worktree";
-	case CONFIG_SCOPE_CMDLINE:
-		return "cmdline";
+	case CONFIG_SCOPE_COMMAND:
+		return "command";
 	default:
 		return "unknown";
 	}
-- 
gitgitgadget


^ permalink raw reply related

* [PATCH v2 0/4] config: allow user to know scope of config options
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers
In-Reply-To: <pull.478.git.1576631464.gitgitgadget@gmail.com>

This was originally a pull request to the git-for-windows repository
[https://github.com/git-for-windows/git/pull/2399]. It adds a new option
--show-scope which would allow a user to see what scope a given
configuration value has (sytem, local, global, etc.).

changes since v1:

 * Cleaned up meaning of scoping, specifically separating "repo" into
   "local" and "worktree" as well as expanding "cmdline" into "command"
   scoping, added submodule scoping
 * Taught struct git_config_source to remember the scope of the command that
   is filling it out
 * do_git_config_sequence() now remembers the previous scope so that if it
   is called recursively it can remember where it was.
 * Added documentation for this new option

Matthew Rogers (4):
  config: fix typo in variable name
  config: fix config scope enum
  config: clarify meaning of command line scoping
  config: add '--show-scope' to print the scope of a config value

 Documentation/git-config.txt | 15 +++++---
 builtin/config.c             | 66 ++++++++++++++++++++++++++++++------
 config.c                     | 15 ++++----
 config.h                     | 19 ++++++-----
 remote.c                     |  3 +-
 submodule-config.c           |  4 ++-
 t/helper/test-config.c       |  8 +++--
 t/t1300-config.sh            | 50 +++++++++++++++++++++++++++
 upload-pack.c                |  3 +-
 9 files changed, 148 insertions(+), 35 deletions(-)


base-commit: 7a6a90c6ec48fc78c83d7090d6c1b95d8f3739c0
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-478%2FROGERSM94%2Fadd-config-flags-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-478/ROGERSM94/add-config-flags-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/478

Range-diff vs v1:

 -:  ---------- > 1:  b40480f03a config: fix typo in variable name
 -:  ---------- > 2:  e8e05f3940 config: fix config scope enum
 -:  ---------- > 3:  8225273546 config: clarify meaning of command line scoping
 1:  ec699bb3e6 ! 4:  92ce9b7824 config: allow user to know scope of config options
     @@ -1,21 +1,62 @@
      Author: Matthew Rogers <mattr94@gmail.com>
      
     -    config: allow user to know scope of config options
     +    config: add '--show-scope' to print the scope of a config value
      
     -    Add new option --show-scope which allows a user to know what the scope
     -    of listed config options are (local/global/system/etc.).
     +    When a user queries config values with --show-origin, often it's
     +    difficult to determine what the actual "scope" (local, global, etc.) of
     +    a given value is based on just the origin file.
     +
     +    Teach 'git config' the '--show-scope' option to print the scope of all
     +    displayed config values.  Note that we should never see anything of
     +    "submodule" scope as that is only ever used by submodule-config.c when
     +    parsing the '.gitmodules' file.
      
          Signed-off-by: Matthew Rogers <mattr94@gmail.com>
      
     + diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
     + --- a/Documentation/git-config.txt
     + +++ b/Documentation/git-config.txt
     +@@
     + SYNOPSIS
     + --------
     + [verse]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] name [value [value_regex]]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] name [value [value_regex]]
     + 'git config' [<file-option>] [--type=<type>] --add name value
     + 'git config' [<file-option>] [--type=<type>] --replace-all name value [value_regex]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get name [value_regex]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] --get-all name [value_regex]
     +-'git config' [<file-option>] [--type=<type>] [--show-origin] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get name [value_regex]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] --get-all name [value_regex]
     ++'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
     + 'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch name URL
     + 'git config' [<file-option>] --unset name [value_regex]
     + 'git config' [<file-option>] --unset-all name [value_regex]
     + 'git config' [<file-option>] --rename-section old_name new_name
     + 'git config' [<file-option>] --remove-section name
     +-'git config' [<file-option>] [--show-origin] [-z|--null] [--name-only] -l | --list
     ++'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list
     + 'git config' [<file-option>] --get-color name [default]
     + 'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
     + 'git config' [<file-option>] -e | --edit
     +@@
     + 	the actual origin (config file path, ref, or blob id if
     + 	applicable).
     + 
     ++--show-scope::
     ++	Similar to `--show-origin` in that it augments the output of
     ++	all queried config options with the scope of that value 
     ++	(local, global, system, command).
     ++
     + --get-colorbool name [stdout-is-tty]::
     + 
     + 	Find the color setting for `name` (e.g. `color.diff`) and output
     +
       diff --git a/builtin/config.c b/builtin/config.c
       --- a/builtin/config.c
       +++ b/builtin/config.c
      @@
     - static struct git_config_source given_config_source;
     - static int actions, type;
     - static char *default_value;
     --static int end_null;
     -+static int end_nul;
       static int respect_includes_opt = -1;
       static struct config_options config_options;
       static int show_origin;
     @@ -24,69 +65,41 @@
       #define ACTION_GET (1<<0)
       #define ACTION_GET_ALL (1<<1)
      @@
     - 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
     - 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
     - 	OPT_GROUP(N_("Other")),
     --	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
     -+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
       	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
       	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
       	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
     -+	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (system, global, local, command line)")),
     ++	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
       	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
       	OPT_END(),
       };
      @@
     - 
     - static void show_config_origin(struct strbuf *buf)
     - {
     --	const char term = end_null ? '\0' : '\t';
     -+	const char term = end_nul ? '\0' : '\t';
     - 
     - 	strbuf_addstr(buf, current_config_origin_type());
     - 	strbuf_addch(buf, ':');
     --	if (end_null)
     -+	if (end_nul)
     - 		strbuf_addstr(buf, current_config_name());
     - 	else
     - 		quote_c_style(current_config_name(), buf, NULL, 0);
       	strbuf_addch(buf, term);
       }
       
      +static const char *scope_to_string(enum config_scope scope) {
     -+	/*
     -+	 * --local, --global, and --system work the same as --file so there's
     -+	 * no easy way for the parser to tell the difference when it is
     -+	 * setting the scope, so we use our information about which options
     -+	 * were passed
     -+	 */
     -+	if (use_local_config || scope == CONFIG_SCOPE_REPO) {
     ++	switch (scope) {
     ++	case CONFIG_SCOPE_LOCAL:
      +		return "local";
     -+	} else if (use_global_config || scope == CONFIG_SCOPE_GLOBAL) {
     ++	case CONFIG_SCOPE_GLOBAL:
      +		return "global";
     -+	} else if (use_system_config || scope == CONFIG_SCOPE_SYSTEM) {
     ++	case CONFIG_SCOPE_SYSTEM:
      +		return "system";
     -+	} else if (given_config_source.use_stdin ||
     -+		given_config_source.blob ||
     -+		given_config_source.file ||
     -+		scope == CONFIG_SCOPE_CMDLINE) {
     -+		return "command line";
     -+	} else {
     ++	case CONFIG_SCOPE_WORKTREE:
     ++		return "worktree";
     ++	case CONFIG_SCOPE_COMMAND:
     ++		return "command";
     ++	case CONFIG_SCOPE_SUBMODULE:
     ++		return "submodule";
     ++	default:
      +		return "unknown";
      +	}
      +}
      +
     -+static void show_config_scope(struct strbuf *buf)
     -+{
     ++static void show_config_scope(struct strbuf *buf) {
      +	const char term = end_nul ? '\0' : '\t';
      +	const char *scope = scope_to_string(current_config_scope());
      +
     -+	strbuf_addch(buf, '(');
     -+	if (end_nul)
     -+		strbuf_addstr(buf, N_(scope));
     -+	else
     -+		quote_c_style(scope, buf, NULL, 0);
     -+	strbuf_addch(buf, ')');
     ++	strbuf_addstr(buf, N_(scope));
      +	strbuf_addch(buf, term);
      +}
      +
     @@ -96,33 +109,188 @@
      +	if (show_origin || show_scope) {
       		struct strbuf buf = STRBUF_INIT;
      -		show_config_origin(&buf);
     --		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
      +		if (show_scope)
      +			show_config_scope(&buf);
      +		if (show_origin)
      +			show_config_origin(&buf);
     -+		/* Use fwrite as "buf" can contain \0's if "end_nul" is set. */
     + 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
       		fwrite(buf.buf, 1, buf.len, stdout);
       		strbuf_release(&buf);
     - 	}
      @@
       
       static int format_config(struct strbuf *buf, const char *key_, const char *value_)
       {
      +	if (show_scope)
     -+		show_config_scope(buf);
     ++		show_config_origin(buf);
       	if (show_origin)
       		show_config_origin(buf);
       	if (show_keys)
      @@
     - 		config_options.git_dir = get_git_dir();
     + 	int nongit = !startup_info->have_repository;
     + 	char *value;
     + 
     ++
     ++
     + 	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
     + 
     + 	argc = parse_options(argc, argv, prefix, builtin_config_options,
     +@@
     + 			!strcmp(given_config_source.file, "-")) {
     + 		given_config_source.file = NULL;
     + 		given_config_source.use_stdin = 1;
     ++		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     + 	}
     + 
     + 	if (use_global_config) {
     +@@
     + 			 */
     + 			die(_("$HOME not set"));
     + 
     ++		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
     ++
     + 		if (access_or_warn(user_config, R_OK, 0) &&
     + 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
     + 			given_config_source.file = xdg_config;
     +@@
     + 			free(xdg_config);
     + 		}
     + 	}
     +-	else if (use_system_config)
     ++	else if (use_system_config) {
     + 		given_config_source.file = git_etc_gitconfig();
     +-	else if (use_local_config)
     ++		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
     ++	} else if (use_local_config) {
     + 		given_config_source.file = git_pathdup("config");
     +-	else if (use_worktree_config) {
     ++		given_config_source.scope = CONFIG_SCOPE_LOCAL;
     ++	} else if (use_worktree_config) {
     + 		struct worktree **worktrees = get_worktrees(0);
     + 		if (repository_format_worktree_config)
     + 			given_config_source.file = git_pathdup("config.worktree");
     +@@
     + 			      "section in \"git help worktree\" for details"));
     + 		else
     + 			given_config_source.file = git_pathdup("config");
     ++		given_config_source.scope = CONFIG_SCOPE_LOCAL;
     + 		free_worktrees(worktrees);
     + 	} else if (given_config_source.file) {
     + 		if (!is_absolute_path(given_config_source.file) && prefix)
     + 			given_config_source.file =
     + 				prefix_filename(prefix, given_config_source.file);
     ++		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     ++	} else if (given_config_source.blob) {
     ++		given_config_source.scope = CONFIG_SCOPE_COMMAND;
     + 	}
     + 
     ++
     + 	if (respect_includes_opt == -1)
     + 		config_options.respect_includes = !given_config_source.file;
     + 	else
     +
     + diff --git a/config.c b/config.c
     + --- a/config.c
     + +++ b/config.c
     +@@
     + 	char *xdg_config = xdg_config_home("config");
     + 	char *user_config = expand_user_path("~/.gitconfig", 0);
     + 	char *repo_config;
     ++	enum config_scope prev_parsing_scope = current_parsing_scope;
     + 
     + 	if (opts->commondir)
     + 		repo_config = mkpathdup("%s/config", opts->commondir);
     +@@
     + 	if (!opts->ignore_cmdline && git_config_from_parameters(fn, data) < 0)
     + 		die(_("unable to parse command-line config"));
     + 
     +-	current_parsing_scope = CONFIG_SCOPE_UNKNOWN;
     ++	current_parsing_scope = prev_parsing_scope;
     + 	free(xdg_config);
     + 	free(user_config);
     + 	free(repo_config);
     +@@
     + 		data = &inc;
       	}
       
     --	if (end_null) {
     -+	if (end_nul) {
     - 		term = '\0';
     - 		delim = '\n';
     - 		key_delim = '\n';
     ++	if (config_source)
     ++		current_parsing_scope = config_source->scope;
     ++
     + 	/*
     + 	 * If we have a specific filename, use it. Otherwise, follow the
     + 	 * regular lookup sequence.
     +
     + diff --git a/config.h b/config.h
     + --- a/config.h
     + +++ b/config.h
     +@@
     + 
     + #define CONFIG_REGEX_NONE ((void *)1)
     + 
     ++enum config_scope {
     ++	CONFIG_SCOPE_UNKNOWN = 0,
     ++	CONFIG_SCOPE_SYSTEM,
     ++	CONFIG_SCOPE_GLOBAL,
     ++	CONFIG_SCOPE_LOCAL,
     ++	CONFIG_SCOPE_WORKTREE,
     ++	CONFIG_SCOPE_COMMAND,
     ++	CONFIG_SCOPE_SUBMODULE,
     ++};
     ++
     + struct git_config_source {
     + 	unsigned int use_stdin:1;
     + 	const char *file;
     + 	const char *blob;
     ++	enum config_scope scope;
     + };
     + 
     + enum config_origin_type {
     +@@
     + 
     + int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
     + 
     +-enum config_scope {
     +-	CONFIG_SCOPE_UNKNOWN = 0,
     +-	CONFIG_SCOPE_SYSTEM,
     +-	CONFIG_SCOPE_GLOBAL,
     +-	CONFIG_SCOPE_LOCAL,
     +-	CONFIG_SCOPE_WORKTREE,
     +-	CONFIG_SCOPE_COMMAND,
     +-};
     +-
     + enum config_scope current_config_scope(void);
     + const char *current_config_origin_type(void);
     + const char *current_config_name(void);
     +
     + diff --git a/submodule-config.c b/submodule-config.c
     + --- a/submodule-config.c
     + +++ b/submodule-config.c
     +@@
     + static void config_from_gitmodules(config_fn_t fn, struct repository *repo, void *data)
     + {
     + 	if (repo->worktree) {
     +-		struct git_config_source config_source = { 0 };
     ++		struct git_config_source config_source = {
     ++			0, .scope = CONFIG_SCOPE_SUBMODULE
     ++		};
     + 		const struct config_options opts = { 0 };
     + 		struct object_id oid;
     + 		char *file;
     +
     + diff --git a/t/helper/test-config.c b/t/helper/test-config.c
     + --- a/t/helper/test-config.c
     + +++ b/t/helper/test-config.c
     +@@
     + 		return "repo";
     + 	case CONFIG_SCOPE_WORKTREE:
     + 		return "worktree";
     ++	case CONFIG_SCOPE_SUBMODULE:
     ++		return "submodule";
     + 	case CONFIG_SCOPE_COMMAND:
     +-		return "command";
     ++		return "cmdline";
     + 	default:
     + 		return "unknown";
     + 	}
      
       diff --git a/t/t1300-config.sh b/t/t1300-config.sh
       --- a/t/t1300-config.sh
     @@ -131,18 +299,17 @@
       	test_cmp expect output
       '
       
     -+
      +test_expect_success '--show-scope with --list' '
      +	cat >expect <<-EOF &&
     -+		(global)	user.global=true
     -+		(global)	user.override=global
     -+		(global)	include.path=$INCLUDE_DIR/absolute.include
     -+		(global)	user.absolute=include
     -+		(local)	user.local=true
     -+		(local)	user.override=local
     -+		(local)	include.path=../include/relative.include
     -+		(local)	user.relative=include
     -+		(command line)	user.cmdline=true
     ++		global	user.global=true
     ++		global	user.override=global
     ++		global	include.path=$INCLUDE_DIR/absolute.include
     ++		global	user.absolute=include
     ++		local	user.local=true
     ++		local	user.override=local
     ++		local	include.path=../include/relative.include
     ++		local	user.relative=include
     ++		command	user.cmdline=true
      +	EOF
      +	git -c user.cmdline=true config --list --show-scope >output &&
      +	test_cmp expect output
     @@ -151,16 +318,16 @@
      +test_expect_success !MINGW '--show-scope with --blob' '
      +	blob=$(git hash-object -w "$CUSTOM_CONFIG_FILE") &&
      +	cat >expect <<-EOF &&
     -+		(command line)	user.custom=true
     ++		command	user.custom=true
      +	EOF
      +	git config --blob=$blob --show-scope --list >output &&
      +	test_cmp expect output
      +'
      +test_expect_success '--show-scope with --local' '
      +	cat >expect <<-\EOF &&
     -+		(local)	user.local=true
     -+		(local)	user.override=local
     -+		(local)	include.path=../include/relative.include
     ++		local	user.local=true
     ++		local	user.override=local
     ++		local	include.path=../include/relative.include
      +	EOF
      +	git config --local --list --show-scope >output &&
      +	test_cmp expect output
     @@ -168,15 +335,15 @@
      +
      +test_expect_success '--show-scope with --show-origin' '
      +	cat >expect <<-EOF &&
     -+		(global)	file:$HOME/.gitconfig	user.global=true
     -+		(global)	file:$HOME/.gitconfig	user.override=global
     -+		(global)	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
     -+		(global)	file:$INCLUDE_DIR/absolute.include	user.absolute=include
     -+		(local)	file:.git/config	user.local=true
     -+		(local)	file:.git/config	user.override=local
     -+		(local)	file:.git/config	include.path=../include/relative.include
     -+		(local)	file:.git/../include/relative.include	user.relative=include
     -+		(command line)	command line:	user.cmdline=true
     ++		global	file:$HOME/.gitconfig	user.global=true
     ++		global	file:$HOME/.gitconfig	user.override=global
     ++		global	file:$HOME/.gitconfig	include.path=$INCLUDE_DIR/absolute.include
     ++		global	file:$INCLUDE_DIR/absolute.include	user.absolute=include
     ++		local	file:.git/config	user.local=true
     ++		local	file:.git/config	user.override=local
     ++		local	file:.git/config	include.path=../include/relative.include
     ++		local	file:.git/../include/relative.include	user.relative=include
     ++		command	command line:	user.cmdline=true
      +	EOF
      +	git -c user.cmdline=true config --list --show-origin --show-scope >output &&
      +	test_cmp expect output

-- 
gitgitgadget

^ permalink raw reply

* [PATCH v2 2/4] config: fix config scope enum
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers
In-Reply-To: <pull.478.v2.git.1578565001.gitgitgadget@gmail.com>

From: Matthew Rogers <mattr94@gmail.com>

Previously when iterating through git config variables, worktree config
and local config were both considered "CONFIG_SCOPE_REPO".  This was
never a problem before as no one had needed to differentiate between the
two cases.

Additionally we rename what was CONFIG_SCOPE_REPO to CONFIG_SCOPE_LOCAL
to reflect its new, more specific meaning.

The clients of 'current_config_scope()' who cared about
CONFIG_SCOPE_REPO are also modified to similarly care about
CONFIG_SCOPE_WORKTREE and CONFIG_SCOPE_LOCAL to preserve previous behavior.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 config.c               | 7 ++-----
 config.h               | 3 ++-
 remote.c               | 3 ++-
 t/helper/test-config.c | 4 +++-
 upload-pack.c          | 3 ++-
 5 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/config.c b/config.c
index d75f88ca0c..447a013a15 100644
--- a/config.c
+++ b/config.c
@@ -1724,15 +1724,12 @@ static int do_git_config_sequence(const struct config_options *opts,
 	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK))
 		ret += git_config_from_file(fn, user_config, data);
 
-	current_parsing_scope = CONFIG_SCOPE_REPO;
+	current_parsing_scope = CONFIG_SCOPE_LOCAL;
 	if (!opts->ignore_repo && repo_config &&
 	    !access_or_die(repo_config, R_OK, 0))
 		ret += git_config_from_file(fn, repo_config, data);
 
-	/*
-	 * Note: this should have a new scope, CONFIG_SCOPE_WORKTREE.
-	 * But let's not complicate things before it's actually needed.
-	 */
+	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
 	if (!opts->ignore_worktree && repository_format_worktree_config) {
 		char *path = git_pathdup("config.worktree");
 		if (!access_or_die(path, R_OK, 0))
diff --git a/config.h b/config.h
index 91fd4c5e96..284d92fb0e 100644
--- a/config.h
+++ b/config.h
@@ -298,7 +298,8 @@ enum config_scope {
 	CONFIG_SCOPE_UNKNOWN = 0,
 	CONFIG_SCOPE_SYSTEM,
 	CONFIG_SCOPE_GLOBAL,
-	CONFIG_SCOPE_REPO,
+	CONFIG_SCOPE_LOCAL,
+	CONFIG_SCOPE_WORKTREE,
 	CONFIG_SCOPE_CMDLINE,
 };
 
diff --git a/remote.c b/remote.c
index 5c4666b53a..593ce297ed 100644
--- a/remote.c
+++ b/remote.c
@@ -369,7 +369,8 @@ static int handle_config(const char *key, const char *value, void *cb)
 	}
 	remote = make_remote(name, namelen);
 	remote->origin = REMOTE_CONFIG;
-	if (current_config_scope() == CONFIG_SCOPE_REPO)
+	if (current_config_scope() == CONFIG_SCOPE_LOCAL ||
+	current_config_scope() == CONFIG_SCOPE_WORKTREE)
 		remote->configured_in_repo = 1;
 	if (!strcmp(subkey, "mirror"))
 		remote->mirror = git_config_bool(key, value);
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 214003d5b2..6695e463eb 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -44,8 +44,10 @@ static const char *scope_name(enum config_scope scope)
 		return "system";
 	case CONFIG_SCOPE_GLOBAL:
 		return "global";
-	case CONFIG_SCOPE_REPO:
+	case CONFIG_SCOPE_LOCAL:
 		return "repo";
+	case CONFIG_SCOPE_WORKTREE:
+		return "worktree";
 	case CONFIG_SCOPE_CMDLINE:
 		return "cmdline";
 	default:
diff --git a/upload-pack.c b/upload-pack.c
index a00d7ece6b..c53249cac1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1073,7 +1073,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
 		precomposed_unicode = git_config_bool(var, value);
 	}
 
-	if (current_config_scope() != CONFIG_SCOPE_REPO) {
+	if (current_config_scope() != CONFIG_SCOPE_LOCAL &&
+	current_config_scope() != CONFIG_SCOPE_WORKTREE) {
 		if (!strcmp("uploadpack.packobjectshook", var))
 			return git_config_string(&pack_objects_hook, var, value);
 	}
-- 
gitgitgadget


^ permalink raw reply related

* [PATCH v2 1/4] config: fix typo in variable name
From: Matthew Rogers via GitGitGadget @ 2020-01-09 10:16 UTC (permalink / raw)
  To: git; +Cc: Matthew Rogers, Matthew Rogers
In-Reply-To: <pull.478.v2.git.1578565001.gitgitgadget@gmail.com>

From: Matthew Rogers <mattr94@gmail.com>

In git config use of the end_null variable to determine if we should be
null terminating our output.  While it is correct to say a string is
"null terminated" the character is actually the "nul" character, so this
malapropism is being fixed.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
---
 builtin/config.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 98d65bc0ad..52a904cfb1 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -29,7 +29,7 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_null;
+static int end_nul;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
@@ -151,7 +151,7 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
@@ -178,11 +178,11 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_null ? '\0' : '\t';
+	const char term = end_nul ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_null)
+	if (end_nul)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
@@ -678,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_null) {
+	if (end_nul) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
-- 
gitgitgadget


^ permalink raw reply related

* Re: [PATCH 1/1] worktree: delete branches auto-created by 'worktree add'
From: Eric Sunshine @ 2020-01-09  9:46 UTC (permalink / raw)
  To: Pratyush Yadav; +Cc: Git List
In-Reply-To: <20200106180101.wwznvthla35x3qd2@yadavpratyush.com>

On Mon, Jan 6, 2020 at 1:01 PM Pratyush Yadav <me@yadavpratyush.com> wrote:
> On 05/01/20 11:20PM, Eric Sunshine wrote:
> > On Fri, Dec 27, 2019 at 6:05 AM Eric Sunshine <sunshine@sunshineco.com> wrote:
> > As an alternative to this patch, would the simpler approach of
> > improving git-worktree documentation to do a better job of pointing
> > people at -d/--detach as a way to side-step unwanted branch creation
> > make sense? That is, at minimum, enhance the "Description" section to
> > prominently talk about throwaway worktrees (created with -d/--detach),
> > and add an example to the "Examples" section (perhaps as the first
> > example) showing creation/use/deletion of a throwaway worktree.
>
> FYI, I'm running Git v2.24.1 and 'git worktree add' doesn't accept the
> option '-d'. It only accepts '--detach'. And looking at the current
> 'next', I don't see the option mentioned in git-worktree.txt. So at the
> very least, we should start by actually adding the option.

I forgot that -d was never added as shorthand for --detach, and didn't
bother checking the man page. But, yes, adding -d would be a good
start.

> > Of lesser importance, it might make sense, as a followup, to add a
> > configuration which changes the default behavior to detach instead of
> > auto-creating a branch. I wonder if this could be piggybacked on the
> > existing "worktree.guessremote" configuration. Or rather,
> > retire/deprecate that configuration and add a new one which affects
> > DWIM'ing behavior such that it becomes multi-state. Some possible
> > values for the new configuration: "auto" (or "dwim" or whatever),
> > "guessremote", "detach". (I haven't thought this through thoroughly,
> > so there might be holes in my suggestion.)
>
> Honestly, coupled with a configuration variable this alternative fits my
> use-case really well.
>
> I think 'guessremote' does not describe very well what the config
> variable would actually do. So I think deprecating it would be a better
> idea.
>
> Does 'worktree.newBranch' sound like a good name? (Disclaimer: I am
> terrible at naming things).

Maybe 'worktree.addFlags' or something? I'm thinking that this might
be a multi-value configuration variable which is a combination of the
various option flags which can be used with "git worktree add". For
instance: 'worktree.addFlags=detach' or
worktree.addFlags=auto-create-branch,guess-remote. Possible values
might include:

[no-]auto-create-branch
    enable/disable automatic branch creation when <commit-ish> is
    omitted

detach
    create worktree with detached HEAD

[no-]checkout
    perform/suppress checkout of <commit-ish> in the new worktree

[no-]guess-remote
    create local branch from remote-tracking branch if present and
    <commit-ish> omitted

[no-]track
    make new branch track <commit-ish> if the latter is a branch name

[no-]lock
    keep worktree locked after creation

In fact, I'd like to see 'auto-create-branch' incorporate
'guess-remote' behavior by default since "remote guessing" should have
been the default behavior from day one, but it was overlooked. The
--guess-remote option was added simply to avoid backward compatibility
problems, but it would be nice to one day make it the default. Since
this configuration variable is new, we don't have to worry about
backward compatibility with it, thus can make 'auto-create-branch'
work like it should have from inception -- that is, performing "remote
guessing" DWIMing (just like "git checkout" does by default).

A command-line option would (as expected) override a flag set via
'worktree.addFlags'. So, for instance, --no-detach would override
'worktree.addFlags=detach'.

Anyhow, this is just a rough idea. I haven't thought through all the
ramifications, or even if this is a sane interface.

> > There's at least one point not in favor of merely updating the
> > documentation to promote -d/--detach more heavily, and that is that
> > (presumably) the concept of detached HEAD is perceived as an advanced
> > topic, so it may not be suitable for the newcomer or casual user.
>
> I'm basing this off no data so take it with a grain of salt, but I think
> people who know Git enough to understand the concept of multiple
> worktrees should also understand what a detached HEAD is. And even if
> they already don't know what it is, they should have no trouble quickly
> reading one of the many great explanations available with a simple
> Google search.

I don't necessarily share that opinion, but I do think that if we add
-d as shorthand for --detach, and do a really good job of updating the
documentation to promote the idea of "throwaway worktrees" (which also
happen to be detached), then we have a good path forward.

> My argument in favor of auto-deletion is that we should still try to
> have sane defaults. Leaving behind a branch the user didn't explicitly
> create and didn't use doesn't sound like a sane default to me.
>
> The configuration variable path is easier and suits my needs really
> well, so I am inclined to just go with it. But making the whole user
> experience better for everyone is still something worthwhile. But then
> again, introducing a backwards-incompatible change might not be the best
> idea. So, I dunno.

Yep, the different ideas can co-exist, and each can be implemented
without promising to implement the others. A good first step would be
to add -d as alias for --detach and update the documentation to
promote the concept of "throwaway worktrees". An optional second step
(if needed) would be that new configuration variable (though it still
needs more thought). And, a really optional third step (if anyone
cares strongly enough) would be to implement auto-deletion of
auto-created branches.

^ permalink raw reply

* Re: Broken branch after git commit - tracked files in staging area can't be removed with restore --staged, or commit or stash
From: Jeff King @ 2020-01-09  9:39 UTC (permalink / raw)
  To: Torsten Krah; +Cc: git@vger.kernel.org
In-Reply-To: <654cc7a58cf6947f91478411dd6a3f7f3473bc67.camel@gmail.com>

On Wed, Jan 08, 2020 at 01:42:14PM +0100, Torsten Krah wrote:

> thanks for confirming those bugs and taking a look at my report itself
> even before I've put the small reproducer recipe.
> I don't need to take any other actions or create tickets somewhere else
> now to get those fixed, you're driving this from here, right?

Correct.

> Another question - how can I fix my broken original branch where this
> bug did hit me which is in that "bogus" state now to get back to the
> "original" commit made so I can remove my unwanted files with "git
> reset HEAD <files>" instead of git-restore in the meantime (tried your
> rm .git/index variant but after that I had files which were already in
> the branch shown as unversioned after that, so that did not work very
> well for me)?

You should be able to do:

  git checkout your-branch
  git reset --hard <original>

to go back to the state you were at (this is assuming you haven't built
more commits on top, of course), and then repeat your steps. That should
also clear out any breakage in the index, since "reset --hard" will
invalidate the cache-tree as necessary.

If you need to find the commit id of that original commit, try looking
in the reflog for your branch: git log -g your-branch

-Peff

^ permalink raw reply

* Re: interoperability between git and other VCS and data storage/transfer tools?
From: Paul Wise @ 2020-01-09  8:16 UTC (permalink / raw)
  To: git
In-Reply-To: <20200109075748.GB3978837@coredump.intra.peff.net>

[-- Attachment #1: Type: text/plain, Size: 410 bytes --]

On Thu, 2020-01-09 at 02:57 -0500, Jeff King wrote:

> https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#Interaction_with_other_Revision_Control_Systems
> I have no idea how up-to-date it is

It seems to miss a number of tools, I've requested an account and will
update it with the tools I know about. Thanks for all the pointers.

-- 
bye,
pabs

https://bonedaddy.net/pabs3/

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH] clone: teach --single-branch and --branch during --recurse
From: Jeff King @ 2020-01-09  8:11 UTC (permalink / raw)
  To: Emily Shaffer; +Cc: git
In-Reply-To: <20200108231900.192476-1-emilyshaffer@google.com>

On Wed, Jan 08, 2020 at 03:19:00PM -0800, Emily Shaffer wrote:

> Subject: clone: teach --single-branch and --branch during --recurse

A minor nit, but this subject confused me for a moment. I think we'd
usually say "teach" for a new feature being implemented, and this is
really just about passing along the existing features. Something like:

  clone: pass --single-branch and --branch when recursing submodules

would have been a bit more obvious (to me anyway).

> Previously, performing "git clone --recurse-submodules --single-branch"
> resulted in submodules cloning all branches even though the superproject
> cloned only one branch. Pipe --single-branch and its friend, --branch,
> through the submodule helper framework to make it to 'clone' later on.

Since I don't really use submodules, I don't have much data or even
intuition to go on. But could this be a regression for some situations?
E.g., imagine I have a repo "parent" whose branch "foo" has a submodule
"child", but "child" only has a branch "bar". What happens now if I "git
clone --recurse-submodules --single-branch -b foo parent", and what will
happen after this patch?

I think it works before, but doesn't now.

Setting up like this:

  git init child
  (
  	cd child
  	git checkout -b bar
  	echo whatever >file
  	git add file
  	git commit -m 'child commit'
  )
  
  git init parent
  cd parent
  git checkout -b foo
  git submodule add $PWD/../child
  git commit -m 'add submodule'

if I use the current tip of master, I get:

  $ git clone --recurse-submodules --single-branch -b foo parent cur
  Cloning into 'cur'...
  done.
  Submodule 'child' (/home/peff/tmp/parent/../child) registered for path 'child'
  Cloning into '/home/peff/tmp/cur/child'...
  done.
  Submodule path 'child': checked out 'b5cbfcc9fec3b7d67e305468624fed2ba1aa4758'

  $ git -C cur/child log -1 --oneline | cat
  b5cbfcc child commit

with your patch, I get:

  $ git.compile clone --recurse-submodules --single-branch -b foo parent new
  Cloning into 'new'...
  done.
  Submodule 'child' (/home/peff/tmp/parent/../child) registered for path 'child'
  Cloning into '/home/peff/tmp/new/child'...
  warning: Could not find remote branch foo to clone.
  fatal: Remote branch foo not found in upstream origin
  fatal: clone of '/home/peff/tmp/parent/../child' into submodule path '/home/peff/tmp/new/child' failed
  Failed to clone 'child'. Retry scheduled
  Cloning into '/home/peff/tmp/new/child'...
  warning: Could not find remote branch foo to clone.
  fatal: Remote branch foo not found in upstream origin
  fatal: clone of '/home/peff/tmp/parent/../child' into submodule path '/home/peff/tmp/new/child' failed
  Failed to clone 'child' a second time, aborting

  $ git -C new/child log -1 --oneline | cat
  11acb3a add submodule

(there's nothing checked out in the submodule).

I have no idea how common this kind of thing would be, and I expect in
most cases your patch would do what people want. But we might need to be
better about retrying without those options when the first clone fails.

-Peff

^ permalink raw reply

* Re: interoperability between git and other VCS and data storage/transfer tools?
From: Jeff King @ 2020-01-09  7:57 UTC (permalink / raw)
  To: Paul Wise; +Cc: git
In-Reply-To: <929fe6f7f41a2abca353df4fd7f602a3e22ceb5f.camel@bonedaddy.net>

On Thu, Jan 09, 2020 at 08:59:51AM +0800, Paul Wise wrote:

> I still need mostly bi-directional interoperability between git and
> CVS, Subversion, Mercurial, Breezy/Bazaar, Darcs, Mediawiki and rsync.
> On the horizon are Fossil and Pijul but I probably won't need those any
> time soon. Recently I had a situation where GNU Arch support would have
> been helpful for viewing historical commit information but I assumed
> that support for it didn't exist so I didn't bother.

I don't know if you need it to be bidirectional, but there is
git-archimport. I'll warn you that it's pretty unmaintained, though so
best of luck. :)

> Is there a location in the git documentation for pointers to software
> (such as git-remote-* helpers) that can help with VCS interoperability?

There's:

  https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools#Interaction_with_other_Revision_Control_Systems

I have no idea how up-to-date it is (I admit that I converted all of my
repos to Git in 2006 and haven't really looked back).

> Mercurial: git-remote-hg (there are lots of forks/implementations)

I haven't used it, but there's also:

  https://github.com/glandium/git-cinnabar

which seems to be actively used and maintained.

-Peff

^ permalink raw reply

* Re: [RFC PATCH] unpack-trees: watch for out-of-range index position
From: Jeff King @ 2020-01-09  7:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Emily Shaffer, git
In-Reply-To: <xmqqo8vd1yb2.fsf@gitster-ct.c.googlers.com>

On Wed, Jan 08, 2020 at 12:35:29PM -0800, Junio C Hamano wrote:

> >> It does not sound like a BUG to me, either, but the new condition
> >> does look correct to me, too.  We can turn it into die() later if
> >> somebody truly cares ;-)
> >> 
> >> Thanks, both.  Will queue.
> >
> > Thanks much for the quick turnaround. If I hear more noise I'll give it
> > a try with die() or error code instead, but for now I'll move on to the
> > next bug on my list. :)
> 
> By the way, it is somewhat sad that we proceeded that far in the
> first place---such a corrupt on-disk index would have caused an
> early die() if we did not get rid of the trailing-hash integrity
> check.

Perhaps. The integrity check only protects against an index that was
modified after the fact, not one that was generated by a buggy Git. I'm
not sure we know how the index that led to this patch got into this
state (though it sounds like Emily has a copy and could check the hash
on it), but other cache-tree segfault I found recently was with an index
with an intact integrity hash.

So I think regardless of the trailing-hash check, we'd always want to be
defensive when reading on-disk data.

-Peff

^ permalink raw reply

* Re: How log log a feaure request
From: Junio C Hamano @ 2020-01-09  4:44 UTC (permalink / raw)
  To: Tymek Majewski; +Cc: git@vger.kernel.org
In-Reply-To: <l0W9VY7TaoqT51RecilbNNTaX35RiCNlJtZKcz04cyKexuG06-bZMlwfor5kCvnIHRRWE7s8TSJLwvA-w4-1poMV_gle8iOzd3-wzFVDUh0=@pm.me>

Tymek Majewski <tmaj@pm.me> writes:

> Hello gurus!
>
> I looked at https://git-scm.com/community but I failed to find a
> place to send feature requests to.
>
> Q: How to submit a feature request (rather than a bug)?

Sending it here, which you did, is how ;-)

> Reasoning:
>
> I believe that if the git checkout message
> "Your branch is up to date with 'origin/branch_name_here'"
> was
> "Your branch is up to date with the *local* branch 'origin/branch_name_here'"
> it would make it clearer to new users what is happening.

I would be sympathetic to the above, if you did not say "local" and
instead say "remote-tracking".  A local branch is what you can check
out and grow its history by making a commit while it is checked out.
Those refs that are updated when you fetch and/or pull from the
remote repository in order to keep track of the branches they have
are called remote-tracking branches.

Because this message is something people see every day when they run
"git checkout", I am not sure if the extra explanation is warranted
or merely annoying, as "origin/branch" notation is used sufficiently
often for the users to grow accustomed to seeing it and knowing what
it is, and after all no user will stay to be a newbie forever.

Another reason why I am somewhat hesitant to endorse the rephrasing
is because the name of a remote-tracking branch in the real life
tends to be longer than just 'origin/master'.  We must keep the
message that comes before the name of the remote-tracking branch
short in order to make it easier to read the message for the users.

So... I dunno.

^ permalink raw reply

* Dropbox do not sync particular files after using git push
From: On Luk @ 2020-01-09  3:18 UTC (permalink / raw)
  To: git
In-Reply-To: <16B44F67-E85E-4D87-A8EC-18ED1B35DB41@webssup.com>

Hi Sir/Madam,

I tried to report this issue to dropbox technical team, but they replied that the issue was not caused by Dropbox, so I try to report to your team as a bug report below:

Everytime I used git to push commit to my remote repo located in my dropbox, some files stuck in syncing status and can’t be able to sync to dropbox. To get those files be synced, I need to do one of the follow steps everytime by manually:

1.	Drag and drop back the file to dropbox using the finder.
OR
2.	Click Pause and resume syncing in dropbox desktop manager.
OR
3.	Restart Dropbox.

To make it clear, I prepared a screen recording to show the issue that I am facing.

www.dropbox.com/s/ivn7qytk0u67v6n/Screen%20Recording%202020-01-03%20at%2012.21.21%20PM.mov?dl=0

This issue only appear after I switch to use my new computer running as macOS 10.15, everything works fine in my old computer running as macOS 10.13.6.

p.s: git version 2.24.1

BRs,

On
-- 










The information in this electronic mail ("e-mail") message is for 
the use of the named recipient(s) only and may be confidential. The 
information may be protected by privilege, work product immunity or other 
applicable law. If you are not the intended recipient(s), the retention, 
dissemination, distribution or copying of this e-mail message is strictly 
prohibited. If you receive this e-mail message in error, please notify me 
immediately by replying to the message and thereafter, delete all copies on 
your system and destroy any hard copies. 

^ permalink raw reply

* Re: [PATCH] submodule add: show 'add --dry-run' stderr when aborting
From: Kyle Meyer @ 2020-01-09  2:39 UTC (permalink / raw)
  To: Josh Steadmon; +Cc: git, Yaroslav O Halchenko
In-Reply-To: <20200108214136.GB63040@google.com>

Josh Steadmon <steadmon@google.com> writes:

> On 2020.01.07 19:31, Kyle Meyer wrote:
[...]
>> +test_expect_success 'submodule add relays add --dry-run stderr' '
>> +	test_when_finished "rm -rf addtest/.git/index.lock" &&
>> +	(
>> +		cd addtest &&
>> +		: >.git/index.lock &&
[...]
> I had to look up what ":" does, but it looks like it's reasonably widely
> used in other tests so that seems fine. However, it looks like you don't
> even need the : command and can just ">.git/index.lock" by itself (see
> the "setup - initial commit" test case in this file for an example).

Indeed.  I spot some recent commits that added new instances of ": >",
so I suspect it's not strongly discouraged in this project, but I'm not
particularly attached to the unneeded colon :>

> Looks good to me. Thanks for the patch!

Thanks for the review!

^ permalink raw reply

* How log log a feaure request
From: Tymek Majewski @ 2020-01-09  2:06 UTC (permalink / raw)
  To: git@vger.kernel.org

Hello gurus!

I looked at https://git-scm.com/community but I failed to find a place to send feature requests to.

Q: How to submit a feature request (rather than a bug)?

----

What is the feature request?

Change git checkout's
"Your branch is up to date with 'origin/branch_name_here'"
(and similar messages)
to
"Your branch is up to date with the *local* branch 'origin/branch_name_here'"

Reasoning:

I believe that if the git checkout message
"Your branch is up to date with 'origin/branch_name_here'"
was
"Your branch is up to date with the *local* branch 'origin/branch_name_here'"
it would make it clearer to new users what is happening.


Cheers
Tymek

^ permalink raw reply

* interoperability between git and other VCS and data storage/transfer tools?
From: Paul Wise @ 2020-01-09  0:59 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 1718 bytes --]

Hi all,

[Please CC me in reply, I am not subscribed]

I would like to be only using git on my local systems but there are
other folks out there who prefer to use different VCS systems.

In addition there are VCS-like data storage systems (such as Mediawiki)
and general data storage/transfer systems where one might want to track
changes using git (such as LDAP and rsync).

I still need mostly bi-directional interoperability between git and
CVS, Subversion, Mercurial, Breezy/Bazaar, Darcs, Mediawiki and rsync.
On the horizon are Fossil and Pijul but I probably won't need those any
time soon. Recently I had a situation where GNU Arch support would have
been helpful for viewing historical commit information but I assumed
that support for it didn't exist so I didn't bother.

Is there a location in the git documentation for pointers to software
(such as git-remote-* helpers) that can help with VCS interoperability?

Is there a place for people interested in VCS interoperability software
to collaboratively maintain them?

Should the VCS interop software in the git git repo move there?

I'm currently using the following tools:

CVS: https://github.com/osamuaoki/git-cvs (slightly better than git-cvsimport)
Subversion: git-svn (not using a git-remote-* workflow)
Mercurial: git-remote-hg (there are lots of forks/implementations)
Breezy/Bazaar: git-remote-bzr (there are lots of forks)
Darcs: nothing as only fast-export/fast-import seems possible
Mediawiki: https://github.com/Git-Mediawiki/Git-Mediawiki
rsync: manually rsyncing and importing commits

What other tools are folks using?

Any other thoughts on this?

-- 
bye,
pabs

https://bonedaddy.net/pabs3/

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox