Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Duy Nguyen
On Fri, Nov 30, 2018 at 1:16 AM Dan Fabulich  wrote:
>
> Other thoughts on a global UI rethink:
>
> One of the most common complaints I hear about git is the conceptual 
> difficulty required in undoing changes. https://ohshitgit.com/
>
> > Git is hard: screwing up is easy, and figuring out how to fix your mistakes 
> > is fucking impossible. Git documentation has this chicken and egg problem 
> > where you can't search for how to get yourself out of a mess, unless you 
> > *already know the name of the thing you need to know about* in order to fix 
> > your problem.
>
> A significant fraction of the top-voted questions on StackOverflow are about 
> undoing changes. https://stackoverflow.com/questions/tagged/git
>
> What if there were a 'git undo' command that could unify the answers to all 
> of these questions?
>
> git undo stage
> git undo rm
> git undo edit (checkout files from the stage)
>
> git undo commit (prompt the user whether to revert or reset)
> git undo reset
> git undo checkout
>
> git undo merge
> git undo pull
> git undo push (prompt the user whether to force push back to the past or 
> whether to revert pushed commits)
> git undo rebase
>
> git undo undo
>
> git undo clean
> git undo delete-branch
> git undo delete-stash
>
> Some of these would be trivial effort, but a lot of them would require 
> fundamental changes in the way git operates. (You can't undo a clean right 
> now because the files are just destroyed.)

We're getting there. The biggest problem I have is how this "git undo"
should work, not the changes behind to support it. For example, if I
pulled then did some rebase, what would "git undo pull" do?
-- 
Duy


Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Junio C Hamano
Duy Nguyen  writes:

> core.uiVersion is a big no no to me. I don't want to go to someone's
> terminal, type something and have a total surprise because they set
> different ui version. If you want a total UI redesign, go with a new
> prefix, like "ng" (for new git) or something instead of "git".

Yup, very good point to keep in mind.


Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Junio C Hamano
Duy Nguyen  writes:

>>
>> OK.  Is "auto-vivify the named branch based on a remote-tracking"
>> also rejected, as it is a confusing behaviour that is a too subtle
>> and implicit, just like the detaching head is, and require --guess
>> or sticking to 'git checkout'?  I think it should.
>
> This touches the "remote" concept which I think is another confusing
> thing for new people (your "master" is not the same as the server's
> "master", aka origin/master) and perhaps this dwim thing helps.
> Frankly I don't do dwim much so I don't know if it's that often used.

I actually think a user who sees a DWIM without understanding what
the user wants to do would perceive magic that sometimes works and
sometimes does not, and some other times it does a random thing that
the user does not even understand what is going on.  And such a
random magic that sometimes works, even if the "sometimes" is "most
of the time", say 85% of the time, would not help user form the
right mental model.

"git checkout master~2" that DWIMs to "git checkout --deatch
master~2", but does totally different thing when "git checkout
master" is given, leaving the user confused "what is so different
between these two?".  Until the user realizes 'master' can serve
both as a branch name and a name for a commit object, while master~2
can only be a name for a commit object and is not a branch name, the
behaviour of the command will stay to be mysterious and DWIMmage
would not help user form the right mental model.  I earlier said
that I agree with your decision to leave the implied form out of
switch-branch for exactly that reason.  

The behaviour falls into the same category as "git checkout frotz"
that DWIMS to "git checkout -b frotz -t remotes/origin/frotz", which
also is mysterious until the user understands your 'master' is unique
and is different from 'master' to everybody else, I would think.


Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Duy Nguyen
On Fri, Nov 30, 2018 at 3:16 AM Junio C Hamano  wrote:
>
> Nguyễn Thái Ngọc Duy   writes:
>
> > 'git switch-branch'
> >
> > - implicit detaching is rejected. If you need to detach, you need to
> >   give --detach. Or stick to 'git checkout'.
>
> OK.  Is "auto-vivify the named branch based on a remote-tracking"
> also rejected, as it is a confusing behaviour that is a too subtle
> and implicit, just like the detaching head is, and require --guess
> or sticking to 'git checkout'?  I think it should.

This touches the "remote" concept which I think is another confusing
thing for new people (your "master" is not the same as the server's
"master", aka origin/master) and perhaps this dwim thing helps.
Frankly I don't do dwim much so I don't know if it's that often used.

> > - -b/-B is renamed to -c/-C with long option names
>
> I did not expect that these two are the only options that would be
> out of place with the command name split, but presumably you looked
> at all options for both of the two new commands to see if they made
> sense in the new context?

Yeah (at least the description in struct option[] array)
--
Duy


Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Duy Nguyen
On Fri, Nov 30, 2018 at 12:05 AM Ævar Arnfjörð Bjarmason
 wrote:
> Assuming greenfield development (which we definitely don't have), I
> don't like the "restore-files" name, but the alternative that makes
> sense is "checkout". Then this "--from" argument could become "git
> checkout-tree  -- ", and we'd have:
>
> git switch 
> git checkout 
> git checkout-tree  -- 
>
> Or maybe that sucks, anyway what I was going to suggest is *if* others
> think that made sense as a "if we designed git today" endgame whether we
> could have an opt-in setting where you set e.g. core.uiVersion=3 (in
> anticipation of Git 3.0) and you'd get that behavior. There could be
> some other setting where core.uiVersion would use the old behavior (or
> with another setting, only warn) if we weren't connected to a terminal.

core.uiVersion is a big no no to me. I don't want to go to someone's
terminal, type something and have a total surprise because they set
different ui version. If you want a total UI redesign, go with a new
prefix, like "ng" (for new git) or something instead of "git".
-- 
Duy


[PATCH] format-patch: do not let its diff-options affect --range-diff (was Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options)

2018-11-29 Thread Junio C Hamano
Junio C Hamano  writes:

> In any case, I tend to agree with the conclusion in the downthread
> by Dscho that we should just clearly mark that invocations of the
> "format-patch --range-diff" command with additional diff options is
> an experimental feature that may not do anything sensible in the
> upcoming release, and declare that the UI to pass diff options to
> affect only the range-diff part may later be invented.  IOW, I am
> coming a bit stronger than Dscho's suggestion in that we should not
> even pretend that we aimed to make the options used for range-diff
> customizable when driven from format-patch in the upcoming release,
> or aimed to make --range-diff option compatible with other diff
> options given to the format-patch command.
>
> I had to delay -rc2 to see these last minute tweaks come to some
> reasonable place to stop at, and I do not think we want to delay the
> final any longer or destablizing it further by piling last minute
> undercooked changes on top.

So how about doing this on top of 'master' instead?  As this leaks
*no* information wrt how range-diff machinery should behave from the
format-patch side by not passing any diffopt, as long as the new
code I added to show_range_diff() comes up with a reasonable default
diffopts (for which I really would appreciate extra sets of eyes to
make sure), this change by definition cannot be wrong (famous last
words).

-- >8 --
Subject: format-patch: do not let its diff-options affect --range-diff

Stop leaking how the primary output of format-patch is customized to
the range-diff machinery and instead let the latter use its own
"reasonable default", in order to correct the breakage introduced by
a5170794 ("Merge branch 'ab/range-diff-no-patch'", 2018-11-18) on
the 'master' front.  "git format-patch --range-diff..." without any
weird diff option started to include the "range-diff --stat" output,
which is rather useless right now, that made the whole thing
unusable and this is probably the least disruptive way to whip the
codebase into a shippable shape.

We may want to later make the range-diff driven by format-patch more
configurable, but that would have to wait until we have a good
design.

Signed-off-by: Junio C Hamano 
---
 Documentation/git-format-patch.txt | 5 +
 builtin/log.c  | 2 +-
 log-tree.c | 2 +-
 range-diff.c   | 6 +-
 range-diff.h   | 5 +
 5 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-format-patch.txt 
b/Documentation/git-format-patch.txt
index aba4c5febe..27304428a1 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -250,6 +250,11 @@ feeding the result to `git send-email`.
feature/v2`), or a revision range if the two versions of the series are
disjoint (for example `git format-patch --cover-letter
--range-diff=feature/v1~3..feature/v1 -3 feature/v2`).
++
+Note that diff options passed to the command affect how the primary
+product of `format-patch` is generated, and they are not passed to
+the underlying `range-diff` machinery used to generate the cover-letter
+material (this may change in the future).
 
 --creation-factor=::
Used with `--range-diff`, tweak the heuristic which matches up commits
diff --git a/builtin/log.c b/builtin/log.c
index 0fe6f9ba1e..5ac18e2848 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1096,7 +1096,7 @@ static void make_cover_letter(struct rev_info *rev, int 
use_stdout,
if (rev->rdiff1) {
fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title);
show_range_diff(rev->rdiff1, rev->rdiff2,
-   rev->creation_factor, 1, >diffopt);
+   rev->creation_factor, 1, NULL);
}
 }
 
diff --git a/log-tree.c b/log-tree.c
index 7a83e99250..b243779a0b 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -762,7 +762,7 @@ void show_log(struct rev_info *opt)
next_commentary_block(opt, NULL);
fprintf_ln(opt->diffopt.file, "%s", opt->rdiff_title);
show_range_diff(opt->rdiff1, opt->rdiff2,
-   opt->creation_factor, 1, >diffopt);
+   opt->creation_factor, 1, NULL);
 
memcpy(_queued_diff, , sizeof(diff_queued_diff));
}
diff --git a/range-diff.c b/range-diff.c
index 767af8c5bb..8e52a85c19 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -460,7 +460,11 @@ int show_range_diff(const char *range1, const char *range2,
struct diff_options opts;
struct strbuf indent = STRBUF_INIT;
 
-   memcpy(, diffopt, sizeof(opts));
+   if (diffopt)
+   memcpy(, diffopt, sizeof(opts));
+   else
+   repo_diff_setup(the_repository, );
+
if (!opts.output_format)
opts.output_format = 

Re: [PATCH 3/5] pack-objects: add --sparse option

2018-11-29 Thread Junio C Hamano
Derrick Stolee  writes:

> You're right that having this hidden as an opt-in config variable
> makes it hard to discover as a typical user.
>
> I would argue that we should actually make the config setting true by
> default, and recommend that servers opt-out. Here are my reasons:
>
> 1. The vast majority of users are clients.
>
> 2. Client users are not likely to know about and tweak these settings.
>
> 3. Server users are more likely to keep an eye on the different knobs
> they can tweak.
>
> 4. Servers should use the reachability bitmaps, which don't use this
> logic anyway.
>
> While _eventually_ we should make this opt-out, we shouldn't do that
> until it has cooked a while.

I actually do not agree.  If the knob gives enough benefit, the
users will learn about it viva voce, and in a few more releases
we'll hear "enough users complain that they have to turn it on,
let's make it the default".  If that does not happen, the knob
does not deserve to be turned on in the first place.

The same applies to many shiny new toys people are discussing
recently on this list (e.g. precious vs expendable and non-overlay
checkout are the ones that immediately come to my mind).

Having said that, I won't be commenting on this shiny new toy before
the final.  I want to see more people help tying the loose ends and
give it final varnish to the upcoming release, as it seems to have
become rockier and larger release than we originally anticipated.


Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Junio C Hamano
Ævar Arnfjörð Bjarmason  writes:

>> What prevents you from using `sq_dequote_to_argv()`?
>
> I mean not just nasty in terms of implementation, yeah we could do it,
> but also a nasty UX for things like --word-diff-regex. I.e. instead of:
>
> --range-diff-word-diff-regex='[0-9"]'
>
> You need:
>
> --range-diff-opts="--word-diff-regex='[0-9\"]'"
>
> Now admittedly that in itself isn't very painful *in this case*, but in
> terms of precedent I really dislike that option, i.e. git having some
> mode where I need to work to escape input to pass to another command.

In addition, sq_dequote are meant to be used on quoted string we
internally produce; I do not think we want to promise that it is
safe to use on a random string that comes from end users.

In any case, I tend to agree with the conclusion in the downthread
by Dscho that we should just clearly mark that invocations of the
"format-patch --range-diff" command with additional diff options is
an experimental feature that may not do anything sensible in the
upcoming release, and declare that the UI to pass diff options to
affect only the range-diff part may later be invented.  IOW, I am
coming a bit stronger than Dscho's suggestion in that we should not
even pretend that we aimed to make the options used for range-diff
customizable when driven from format-patch in the upcoming release,
or aimed to make --range-diff option compatible with other diff
options given to the format-patch command.

I had to delay -rc2 to see these last minute tweaks come to some
reasonable place to stop at, and I do not think we want to delay the
final any longer or destablizing it further by piling last minute
undercooked changes on top.


Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy   writes:

> 'git switch-branch'
>
> - implicit detaching is rejected. If you need to detach, you need to
>   give --detach. Or stick to 'git checkout'.

OK.  Is "auto-vivify the named branch based on a remote-tracking"
also rejected, as it is a confusing behaviour that is a too subtle
and implicit, just like the detaching head is, and require --guess
or sticking to 'git checkout'?  I think it should.

> - -b/-B is renamed to -c/-C with long option names

I did not expect that these two are the only options that would be
out of place with the command name split, but presumably you looked
at all options for both of the two new commands to see if they made
sense in the new context?

> 'git restore-files'
>
> - takes a ref from --from argument, not as a free ref. As a result,
>   '--' is no longer needed. All non-option arguments are pathspec

OK.  That does make things easier to teach, as there is no need for
disambiguation.

> - pathspec is mandatory, you can't do "git restore-files" without any
>   pathspec.
>
> - I just remember -p which is allowed to take no pathspec :( I'll fix
>   it later.

Or leave it out of restore-files as a more advanced feature (just
like detaching with HEAD^0 is left out of switch-branch) that the
user can stick to 'git checkout' to use.

> - Two more fancy features (the "git checkout --index" being the
>   default mode and the backup log for accidental overwrites) are of
>   course still missing. But they are coming.

I am unsure about the wisdom of calling it "--index", though.

The "--index" option is "the command can work only on the index, or
only on the working tree files, or on both the index and the working
tree files, and this option tells it to work in the 'both the index
and the working tree files' mode", but when "restore-files" touches
paths, it always modifies both the index and the working tree, so
the "--index" option does not capture the differences well in this
context [*1*].  As I saw this was described as "not using the usual
'overlay' semantics [*2*]", perhaps --overlay/--no-overlay option
that defaults to --no-overlay is easier to explain.

side note 1.  I think the original mention of "--index" came in
the context of contrasting "git reset" with "git checkout".
"git reset (--hard|--mixed) -- " (that does not move
HEAD), which does not but perhaps should exist, is very much
like "git checkout -- ", and if "reset" were written
after the "--index/--cached" convention was established, "reset
--hard" would have called "reset --index" while "reset --mixed"
would have been "reset --cached" (i.e. only work on the index
and not on the working tree).  And "reset --index "
would have worked by removing paths in  that are not
in the HEAD and updating paths in  that are in the
HEAD, i.e. identical to the non overlay behaviour proposed for
the "git checkout" command.  So calling the non overlay mode
"--index" makes sense in the context of discussing "git reset",
and not in the context of "git checkout".

side note 2.  "git checkout  " grabs entries
from the  that patch  and adds them to the
index and checks them out to the working tree.  If the original
index has entries that match  but do not appear in
, they are left in the result.  That is "overlaying
what was taken from the  on top of what is in the
index".

Having said all that, I will not be looking at the series until 2.20
final.  And I hope more people do the same to concentrate on helping
us prevent the last minute glitch slipping in the final release.

Thanks.


Re: [PATCH/RFC v2 0/7] Introduce new commands switch-branch and checkout-files

2018-11-29 Thread Junio C Hamano
Duy Nguyen  writes:

> On Wed, Nov 28, 2018 at 9:01 PM Duy Nguyen  wrote:
>> should we do
>> something about detached HEAD in this switch-branch command (or
>> whatever its name will be)?
>>
>> This is usually a confusing concept to new users
>
> And it just occurred to me that perhaps we should call this "unnamed
> branch" (at least at high UI level) instead of detached HEAD. It is
> technically not as accurate, but much better to understand.

As I said elsewhere in nearby thread, I agree that "unnamed branch"
is a reasonable way to explain what the state the user is in.  It is
not incorrect per-se that HEAD is detached from anything in refs/ in
such a state, but that is an implementation detail of how the
worktree gets on the unnamed branch (which lasts until the worktree
next gets on a named branch, at which point the unnamed branch
disappears).



Re: [PATCH 1/1] rebase --stat: fix when rebasing to an unrelated history

2018-11-29 Thread Junio C Hamano
Johannes Schindelin  writes:

> But I guess that I should not be so lazy and really use two different
> messages here:
>
>   Changes from  to 
>
> and if there is no merge base,
>
>   Changes in 

Ah, that's excellent.

Thanks.


Re: [PATCH] pack-protocol.txt: accept error packets in any context

2018-11-29 Thread Junio C Hamano
Masaya Suzuki  writes:

> Yes, I did. And it also didn't end up in a build error. Do I have a
> different build option...?

Passig DEVELOPER=Yes to make turns a bit more warnings on (in this
case, I think it was "unused-variable") and also uses -Werror to
turn warnings into errors.


Security Alert. git@vger.kernel.org has password callgsm01. Password must be changed.

2018-11-29 Thread ymarzell
Hello!

I have very bad news for you.
09/08/2018 - on this day I hacked your OS and got full access to your account 
git@vger.kernel.org
On this day your account git@vger.kernel.org has password: callgsm01

So, you can change the password, yes.. But my malware intercepts it every time.

How I made it:
In the software of the router, through which you went online, was a 
vulnerability.
I just hacked this router and placed my malicious code on it.
When you went online, my trojan was installed on the OS of your device.

After that, I made a full dump of your disk (I have all your address book, 
history of viewing sites, all files, phone numbers and addresses of all your 
contacts).

A month ago, I wanted to lock your device and ask for a not big amount of btc 
to unlock.
But I looked at the sites that you regularly visit, and I was shocked by what I 
saw!!!
I'm talk you about sites for adults.

I want to say - you are a BIG pervert. Your fantasy is shifted far away from 
the normal course!

And I got an idea
I made a screenshot of the adult sites where you have fun (do you understand 
what it is about, huh?).
After that, I made a screenshot of your joys (using the camera of your device) 
and glued them together.
Turned out amazing! You are so spectacular!

I'm know that you would not like to show these screenshots to your friends, 
relatives or colleagues.
I think $796 is a very, very small amount for my silence.
Besides, I have been spying on you for so long, having spent a lot of time!

Pay ONLY in Bitcoins!
My BTC wallet: 1HkKgPbcMyfhrdPsbufTFczzVnhyT5snB3

You do not know how to use bitcoins?
Enter a query in any search engine: "how to replenish btc wallet".
It's extremely easy

For this payment I give you two days (48 hours).
As soon as this letter is opened, the timer will work.

After payment, my virus and dirty screenshots with your enjoys will be 
self-destruct automatically.
If I do not receive from you the specified amount, then your device will be 
locked, and all your contacts will receive a screenshots with your "enjoys".

I hope you understand your situation.
- Do not try to find and destroy my virus! (All your data, files and 
screenshots is already uploaded to a remote server)
- Do not try to contact me (you yourself will see that this is impossible, the 
sender address is automatically generated)
- Various security services will not help you; formatting a disk or destroying 
a device will not help, since your data is already on a remote server.

P.S. You are not my single victim. so, I guarantee you that I will not disturb 
you again after payment!
 This is the word of honor hacker

I also ask you to regularly update your antiviruses in the future. This way you 
will no longer fall into a similar situation.

Do not hold evil! I just do my job.
Good luck.



Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Dan Fabulich
Other thoughts on a global UI rethink:

One of the most common complaints I hear about git is the conceptual difficulty 
required in undoing changes. https://ohshitgit.com/

> Git is hard: screwing up is easy, and figuring out how to fix your mistakes 
> is fucking impossible. Git documentation has this chicken and egg problem 
> where you can't search for how to get yourself out of a mess, unless you 
> *already know the name of the thing you need to know about* in order to fix 
> your problem.

A significant fraction of the top-voted questions on StackOverflow are about 
undoing changes. https://stackoverflow.com/questions/tagged/git

What if there were a 'git undo' command that could unify the answers to all of 
these questions?

git undo stage
git undo rm
git undo edit (checkout files from the stage)

git undo commit (prompt the user whether to revert or reset)
git undo reset
git undo checkout

git undo merge
git undo pull
git undo push (prompt the user whether to force push back to the past or 
whether to revert pushed commits)
git undo rebase

git undo undo

git undo clean
git undo delete-branch
git undo delete-stash

Some of these would be trivial effort, but a lot of them would require 
fundamental changes in the way git operates. (You can't undo a clean right now 
because the files are just destroyed.)

-Dan

> On Nov 29, 2018, at 3:05 PM, Ævar Arnfjörð Bjarmason  wrote:
> 
> 
> On Thu, Nov 29 2018, Nguyễn Thái Ngọc Duy wrote:
> 
>> v3 sees switch-branch go back to switch-branch (in v2 it was
>> checkout-branch). checkout-files is also renamed restore-files (v1 was
>> restore-paths). Hopefully we won't see another rename.
>> 
>> I'll try to summarize the differences between the new commands and
>> 'git checkout' down here, but you're welcome to just head to 07/14 and
>> read the new man pages.
>> 
>> 'git switch-branch'
>> 
>> - does not "do nothing", you have to either switch branch, create a
>>  new branch, or detach. "git switch-branch" with no arguments is
>>  rejected.
>> 
>> - implicit detaching is rejected. If you need to detach, you need to
>>  give --detach. Or stick to 'git checkout'.
>> 
>> - -b/-B is renamed to -c/-C with long option names
>> 
>> - of course does not accept pathspec
>> 
>> 'git restore-files'
>> 
>> - takes a ref from --from argument, not as a free ref. As a result,
>>  '--' is no longer needed. All non-option arguments are pathspec
>> 
>> - pathspec is mandatory, you can't do "git restore-files" without any
>>  pathspec.
>> 
>> - I just remember -p which is allowed to take no pathspec :( I'll fix
>>  it later.
>> 
>> - Two more fancy features (the "git checkout --index" being the
>>  default mode and the backup log for accidental overwrites) are of
>>  course still missing. But they are coming.
>> 
>> I did not go replace "detached HEAD" with "unnamed branch" (or "no
>> branch") everywhere because I think a unique term is still good to
>> refer to this concept. Or maybe "no branch" is good enough. I dunno.
> 
> I finally tracked down
> https://redfin.engineering/two-commits-that-wrecked-the-user-experience-of-git-f0075b77eab1
> which I'd remembered reading and couldn't find again in these
> discussions. Re-reading it while one may not 100% agree with the
> author's opinion, it's an interesting rabbit hole.
> 
> I also didn't know about EasyGit, or that Elijah Newren had written
> it. I haven't seen him chime in on this series, and would be interested
> to see what he thinks about it.
> 
> Re the naming question in
> https://public-inbox.org/git/87o9abzv46@evledraar.gmail.com/ &
> seeing that eg-switch exists, I wonder if just s/switch-branch/switch/
> makes more sense.
> 
> Assuming greenfield development (which we definitely don't have), I
> don't like the "restore-files" name, but the alternative that makes
> sense is "checkout". Then this "--from" argument could become "git
> checkout-tree  -- ", and we'd have:
> 
>git switch 
>git checkout 
>git checkout-tree  -- 
> 
> Or maybe that sucks, anyway what I was going to suggest is *if* others
> think that made sense as a "if we designed git today" endgame whether we
> could have an opt-in setting where you set e.g. core.uiVersion=3 (in
> anticipation of Git 3.0) and you'd get that behavior. There could be
> some other setting where core.uiVersion would use the old behavior (or
> with another setting, only warn) if we weren't connected to a terminal.
> 
> I.e. I'm thinking of this as step #2 in a #3 step series. Where this is
> the fully backwards compatible UI improvement, but someone who'd
> e.g. use EasyGit or didn't have backwards compatibility concerns could
> enable step #3 and opt-in to a mode where we'd fixed a bunch of UI warts
> in a backwards-incompatible way.
> 
> What would that mode look like? I'd to work on piling that on top of
> this :)



Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Dan Fabulich
Assuming the great day has come to think about this, one thing I'd love to do 
is to unify the name of the index/stage/cache in command-line parameters and 
the documentation.

The index/stage/cache should have one canonical name, and the documentation 
should support that consistently. My taste is to call it the "stage," but 
references to --index, --keep-index, --no-index, etc. are all over the code, as 
well as legacy references to "--cached".

* You can 'git rm --cached myfile' but you can't 'git rm --staged myfile' or 
'git rm --index myfile'.

* You can 'git diff --no-index' or you can 'git diff --cached' with 'git diff 
--staged' as a synonym, deprioritized in the documentation ("--staged is a 
synonym of --cached"). But you can't 'git diff --index' or 'git diff 
--no-stage' or 'git diff --no-cache'.

* You can 'git stage' but 'git help stage' is only one line long, declaring 
that it's a synonym for 'git add'. 'add' appears in the 'git help' common 
commands, but not 'git stage'. There's no built-in 'git unstage', and certainly 
no appetite for 'git index' or 'git cache'.

* Not to mention all of the plumbing commands: checkout-index, diff-index, 
index-pack, merge-index, show-index, and update-index.

My understanding based on historical threads is that changes like this would be 
unwelcome, even just to add synonyms and standardize the documentation around 
"stage" as the term (leaving the plumbing commands alone), but if 
documentation+synonym patches are welcome here, I'd be very enthusiastic.

-Dan

> On Nov 29, 2018, at 3:05 PM, Ævar Arnfjörð Bjarmason  wrote:
> 
> 
> On Thu, Nov 29 2018, Nguyễn Thái Ngọc Duy wrote:
> 
>> v3 sees switch-branch go back to switch-branch (in v2 it was
>> checkout-branch). checkout-files is also renamed restore-files (v1 was
>> restore-paths). Hopefully we won't see another rename.
>> 
>> I'll try to summarize the differences between the new commands and
>> 'git checkout' down here, but you're welcome to just head to 07/14 and
>> read the new man pages.
>> 
>> 'git switch-branch'
>> 
>> - does not "do nothing", you have to either switch branch, create a
>>  new branch, or detach. "git switch-branch" with no arguments is
>>  rejected.
>> 
>> - implicit detaching is rejected. If you need to detach, you need to
>>  give --detach. Or stick to 'git checkout'.
>> 
>> - -b/-B is renamed to -c/-C with long option names
>> 
>> - of course does not accept pathspec
>> 
>> 'git restore-files'
>> 
>> - takes a ref from --from argument, not as a free ref. As a result,
>>  '--' is no longer needed. All non-option arguments are pathspec
>> 
>> - pathspec is mandatory, you can't do "git restore-files" without any
>>  pathspec.
>> 
>> - I just remember -p which is allowed to take no pathspec :( I'll fix
>>  it later.
>> 
>> - Two more fancy features (the "git checkout --index" being the
>>  default mode and the backup log for accidental overwrites) are of
>>  course still missing. But they are coming.
>> 
>> I did not go replace "detached HEAD" with "unnamed branch" (or "no
>> branch") everywhere because I think a unique term is still good to
>> refer to this concept. Or maybe "no branch" is good enough. I dunno.
> 
> I finally tracked down
> https://redfin.engineering/two-commits-that-wrecked-the-user-experience-of-git-f0075b77eab1
> which I'd remembered reading and couldn't find again in these
> discussions. Re-reading it while one may not 100% agree with the
> author's opinion, it's an interesting rabbit hole.
> 
> I also didn't know about EasyGit, or that Elijah Newren had written
> it. I haven't seen him chime in on this series, and would be interested
> to see what he thinks about it.
> 
> Re the naming question in
> https://public-inbox.org/git/87o9abzv46@evledraar.gmail.com/ &
> seeing that eg-switch exists, I wonder if just s/switch-branch/switch/
> makes more sense.
> 
> Assuming greenfield development (which we definitely don't have), I
> don't like the "restore-files" name, but the alternative that makes
> sense is "checkout". Then this "--from" argument could become "git
> checkout-tree  -- ", and we'd have:
> 
>git switch 
>git checkout 
>git checkout-tree  -- 
> 
> Or maybe that sucks, anyway what I was going to suggest is *if* others
> think that made sense as a "if we designed git today" endgame whether we
> could have an opt-in setting where you set e.g. core.uiVersion=3 (in
> anticipation of Git 3.0) and you'd get that behavior. There could be
> some other setting where core.uiVersion would use the old behavior (or
> with another setting, only warn) if we weren't connected to a terminal.
> 
> I.e. I'm thinking of this as step #2 in a #3 step series. Where this is
> the fully backwards compatible UI improvement, but someone who'd
> e.g. use EasyGit or didn't have backwards compatibility concerns could
> enable step #3 and opt-in to a mode where we'd fixed a bunch of UI warts
> in a backwards-incompatible way.
> 
> What would that mode look like? 

Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Thu, Nov 29 2018, Ævar Arnfjörð Bjarmason wrote:

> On Thu, Nov 29 2018, Nguyễn Thái Ngọc Duy wrote:
>
>> v3 sees switch-branch go back to switch-branch (in v2 it was
>> checkout-branch). checkout-files is also renamed restore-files (v1 was
>> restore-paths). Hopefully we won't see another rename.
>>
>> I'll try to summarize the differences between the new commands and
>> 'git checkout' down here, but you're welcome to just head to 07/14 and
>> read the new man pages.
>>
>> 'git switch-branch'
>>
>> - does not "do nothing", you have to either switch branch, create a
>>   new branch, or detach. "git switch-branch" with no arguments is
>>   rejected.
>>
>> - implicit detaching is rejected. If you need to detach, you need to
>>   give --detach. Or stick to 'git checkout'.
>>
>> - -b/-B is renamed to -c/-C with long option names
>>
>> - of course does not accept pathspec
>>
>> 'git restore-files'
>>
>> - takes a ref from --from argument, not as a free ref. As a result,
>>   '--' is no longer needed. All non-option arguments are pathspec
>>
>> - pathspec is mandatory, you can't do "git restore-files" without any
>>   pathspec.
>>
>> - I just remember -p which is allowed to take no pathspec :( I'll fix
>>   it later.
>>
>> - Two more fancy features (the "git checkout --index" being the
>>   default mode and the backup log for accidental overwrites) are of
>>   course still missing. But they are coming.
>>
>> I did not go replace "detached HEAD" with "unnamed branch" (or "no
>> branch") everywhere because I think a unique term is still good to
>> refer to this concept. Or maybe "no branch" is good enough. I dunno.
>
> I finally tracked down
> https://redfin.engineering/two-commits-that-wrecked-the-user-experience-of-git-f0075b77eab1
> which I'd remembered reading and couldn't find again in these
> discussions. Re-reading it while one may not 100% agree with the
> author's opinion, it's an interesting rabbit hole.
>
> I also didn't know about EasyGit, or that Elijah Newren had written
> it. I haven't seen him chime in on this series, and would be interested
> to see what he thinks about it.
>
> Re the naming question in
> https://public-inbox.org/git/87o9abzv46@evledraar.gmail.com/ &
> seeing that eg-switch exists, I wonder if just s/switch-branch/switch/
> makes more sense.
>
> Assuming greenfield development (which we definitely don't have), I
> don't like the "restore-files" name, but the alternative that makes
> sense is "checkout". Then this "--from" argument could become "git
> checkout-tree  -- ", and we'd have:
>
> git switch 
> git checkout 
> git checkout-tree  -- 
>
> Or maybe that sucks, anyway what I was going to suggest is *if* others
> think that made sense as a "if we designed git today" endgame whether we
> could have an opt-in setting where you set e.g. core.uiVersion=3 (in
> anticipation of Git 3.0) and you'd get that behavior. There could be
> some other setting where core.uiVersion would use the old behavior (or
> with another setting, only warn) if we weren't connected to a terminal.
>
> I.e. I'm thinking of this as step #2 in a #3 step series. Where this is
> the fully backwards compatible UI improvement, but someone who'd
> e.g. use EasyGit or didn't have backwards compatibility concerns could
> enable step #3 and opt-in to a mode where we'd fixed a bunch of UI warts
> in a backwards-incompatible way.
>
> What would that mode look like? I'd to work on piling that on top of
> this :)

(Digging some more)

There's also more interesting prior art at https://gitless.com/ (CC'd
authors) and 2x research papers linked at the bottom of that page which
were briefly discussed on-list before:
https://public-inbox.org/git/20160930191413.002049b94b3908b15881b...@domain007.com/

The "gitless" UI has a "gl checkout" which just takes paths as I was
musing about above (and that Redfin post also suggests).


Re: [PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Thu, Nov 29 2018, Nguyễn Thái Ngọc Duy wrote:

> v3 sees switch-branch go back to switch-branch (in v2 it was
> checkout-branch). checkout-files is also renamed restore-files (v1 was
> restore-paths). Hopefully we won't see another rename.
>
> I'll try to summarize the differences between the new commands and
> 'git checkout' down here, but you're welcome to just head to 07/14 and
> read the new man pages.
>
> 'git switch-branch'
>
> - does not "do nothing", you have to either switch branch, create a
>   new branch, or detach. "git switch-branch" with no arguments is
>   rejected.
>
> - implicit detaching is rejected. If you need to detach, you need to
>   give --detach. Or stick to 'git checkout'.
>
> - -b/-B is renamed to -c/-C with long option names
>
> - of course does not accept pathspec
>
> 'git restore-files'
>
> - takes a ref from --from argument, not as a free ref. As a result,
>   '--' is no longer needed. All non-option arguments are pathspec
>
> - pathspec is mandatory, you can't do "git restore-files" without any
>   pathspec.
>
> - I just remember -p which is allowed to take no pathspec :( I'll fix
>   it later.
>
> - Two more fancy features (the "git checkout --index" being the
>   default mode and the backup log for accidental overwrites) are of
>   course still missing. But they are coming.
>
> I did not go replace "detached HEAD" with "unnamed branch" (or "no
> branch") everywhere because I think a unique term is still good to
> refer to this concept. Or maybe "no branch" is good enough. I dunno.

I finally tracked down
https://redfin.engineering/two-commits-that-wrecked-the-user-experience-of-git-f0075b77eab1
which I'd remembered reading and couldn't find again in these
discussions. Re-reading it while one may not 100% agree with the
author's opinion, it's an interesting rabbit hole.

I also didn't know about EasyGit, or that Elijah Newren had written
it. I haven't seen him chime in on this series, and would be interested
to see what he thinks about it.

Re the naming question in
https://public-inbox.org/git/87o9abzv46@evledraar.gmail.com/ &
seeing that eg-switch exists, I wonder if just s/switch-branch/switch/
makes more sense.

Assuming greenfield development (which we definitely don't have), I
don't like the "restore-files" name, but the alternative that makes
sense is "checkout". Then this "--from" argument could become "git
checkout-tree  -- ", and we'd have:

git switch 
git checkout 
git checkout-tree  -- 

Or maybe that sucks, anyway what I was going to suggest is *if* others
think that made sense as a "if we designed git today" endgame whether we
could have an opt-in setting where you set e.g. core.uiVersion=3 (in
anticipation of Git 3.0) and you'd get that behavior. There could be
some other setting where core.uiVersion would use the old behavior (or
with another setting, only warn) if we weren't connected to a terminal.

I.e. I'm thinking of this as step #2 in a #3 step series. Where this is
the fully backwards compatible UI improvement, but someone who'd
e.g. use EasyGit or didn't have backwards compatibility concerns could
enable step #3 and opt-in to a mode where we'd fixed a bunch of UI warts
in a backwards-incompatible way.

What would that mode look like? I'd to work on piling that on top of
this :)


[PATCH v3 14/14] doc: promote "git switch-branch" and "git restore-files"

2018-11-29 Thread Nguyễn Thái Ngọc Duy
The two new commands "git switch-branch" and "git restore-files" are
added to avoid the confusion of one-command-do-all "git checkout" for
new users. They are also helpful to avoid ambiguation context.

For these reasons, promote them everywhere possible. This includes
documentation, suggestions/advice from other commands...

"git checkout" is also removed from "git help" (i.e. it's no longer
considered a commonly used command)

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/config/advice.txt| 10 +++--
 Documentation/config/checkout.txt  |  5 ++-
 Documentation/git-branch.txt   |  8 ++--
 Documentation/git-check-ref-format.txt |  2 +-
 Documentation/git-format-patch.txt |  2 +-
 Documentation/git-merge-base.txt   |  2 +-
 Documentation/git-rebase.txt   |  2 +-
 Documentation/git-remote.txt   |  2 +-
 Documentation/git-rerere.txt   | 10 ++---
 Documentation/git-reset.txt| 18 -
 Documentation/git-revert.txt   |  2 +-
 Documentation/git-stash.txt|  6 +--
 Documentation/gitattributes.txt|  2 +-
 Documentation/gitcli.txt   |  4 +-
 Documentation/gitcore-tutorial.txt | 18 -
 Documentation/giteveryday.txt  | 24 ++--
 Documentation/githooks.txt |  5 ++-
 Documentation/gittutorial-2.txt|  2 +-
 Documentation/gittutorial.txt  |  4 +-
 Documentation/revisions.txt|  2 +-
 Documentation/user-manual.txt  | 54 +-
 advice.c   | 11 --
 command-list.txt   |  2 +-
 sha1-name.c|  2 +-
 wt-status.c|  2 +-
 25 files changed, 104 insertions(+), 97 deletions(-)

diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt
index 57fcd4c862..bffc503385 100644
--- a/Documentation/config/advice.txt
+++ b/Documentation/config/advice.txt
@@ -35,7 +35,8 @@ advice.*::
state in the output of linkgit:git-status[1], in
the template shown when writing commit messages in
linkgit:git-commit[1], and in the help message shown
-   by linkgit:git-checkout[1] when switching branch.
+   by linkgit:git-switch-branch[1] or
+   linkgit:git-checkout[1] when switching branch.
statusUoption::
Advise to consider using the `-u` option to 
linkgit:git-status[1]
when the command takes more than 2 seconds to enumerate 
untracked
@@ -55,9 +56,10 @@ advice.*::
your information is guessed from the system username and
domain name.
detachedHead::
-   Advice shown when you used linkgit:git-checkout[1] to
-   move to the detach HEAD state, to instruct how to create
-   a local branch after the fact.
+   Advice shown when you used
+   linkgit:git-switch-branch[1] or linkgit:git-checkout[1]
+   to move to the detach HEAD state, to instruct how to
+   create a local branch after the fact.
checkoutAmbiguousRemoteBranchName::
Advice shown when the argument to
linkgit:git-checkout[1] ambiguously resolves to a
diff --git a/Documentation/config/checkout.txt 
b/Documentation/config/checkout.txt
index c4118fa196..81b0d47ced 100644
--- a/Documentation/config/checkout.txt
+++ b/Documentation/config/checkout.txt
@@ -8,8 +8,9 @@ checkout.defaultRemote::
disambiguation. The typical use-case is to set this to
`origin`.
 +
-Currently this is used by linkgit:git-checkout[1] when 'git checkout
-' will checkout the '' branch on another remote,
+Currently this is used by linkgit:git-switch-branch[1] and
+linkgit:git-checkout[1] when 'git checkout '
+will checkout the '' branch on another remote,
 and by linkgit:git-worktree[1] when 'git worktree add' refers to a
 remote branch. This setting might be used for other checkout-like
 commands or functionality in the future.
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index bf5316ffa9..1564df47d2 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -48,7 +48,7 @@ The command's second form creates a new branch head named 

 which points to the current `HEAD`, or  if given.
 
 Note that this will create the new branch, but it will not switch the
-working tree to it; use "git checkout " to switch to the
+working tree to it; use "git switch-branch " to switch to the
 new branch.
 
 When a local branch is started off a remote-tracking branch, Git sets up the
@@ -194,7 +194,7 @@ This option is only applicable in non-verbose mode.
 +
 This behavior is the default when the start point is a remote-tracking branch.
 Set the branch.autoSetupMerge configuration variable to `false` if you
-want `git checkout` and `git branch` to always behave as if `--no-track`

[PATCH v3 05/14] checkout: move 'confict_style' and 'dwim_..' to checkout_opts

2018-11-29 Thread Nguyễn Thái Ngọc Duy
These local variables are referenced by struct option[]. This struct
will soon be broken down, moved away and we can't rely on local
variables anymore. Move these two to struct checkout_opts in
preparation for that.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 1b19328d0a..2423fdbf94 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -44,6 +44,8 @@ struct checkout_opts {
int ignore_skipworktree;
int ignore_other_worktrees;
int show_progress;
+   int dwim_new_local_branch;
+
/*
 * If new checkout options are added, skip_merge_working_tree
 * should be updated accordingly.
@@ -55,6 +57,7 @@ struct checkout_opts {
int new_branch_log;
enum branch_track track;
struct diff_options diff_options;
+   char *conflict_style;
 
int branch_exists;
const char *prefix;
@@ -1239,8 +1242,6 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
struct checkout_opts real_opts;
struct checkout_opts *opts = _opts;
struct branch_info new_branch_info;
-   char *conflict_style = NULL;
-   int dwim_new_local_branch = 1;
int dwim_remotes_matched = 0;
struct option options[] = {
OPT__QUIET(>quiet, N_("suppress progress reporting")),
@@ -1265,12 +1266,12 @@ int cmd_checkout(int argc, const char **argv, const 
char *prefix)
OPT_BOOL_F(0, "overwrite-ignore", >overwrite_ignore,
   N_("update ignored files (default)"),
   PARSE_OPT_NOCOMPLETE),
-   OPT_STRING(0, "conflict", _style, N_("style"),
+   OPT_STRING(0, "conflict", >conflict_style, N_("style"),
   N_("conflict style (merge or diff3)")),
OPT_BOOL('p', "patch", >patch_mode, N_("select hunks 
interactively")),
OPT_BOOL(0, "ignore-skip-worktree-bits", 
>ignore_skipworktree,
 N_("do not limit pathspecs to sparse entries only")),
-   OPT_HIDDEN_BOOL(0, "guess", _new_local_branch,
+   OPT_HIDDEN_BOOL(0, "guess", >dwim_new_local_branch,
N_("second guess 'git checkout 
'")),
OPT_BOOL(0, "ignore-other-worktrees", 
>ignore_other_worktrees,
 N_("do not check if another worktree is holding the 
given ref")),
@@ -1286,6 +1287,7 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
opts->overwrite_ignore = 1;
opts->prefix = prefix;
opts->show_progress = -1;
+   opts->dwim_new_local_branch = 1;
 
git_config(git_checkout_config, opts);
 
@@ -1301,9 +1303,9 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
opts->show_progress = isatty(2);
}
 
-   if (conflict_style) {
+   if (opts->conflict_style) {
opts->merge = 1; /* implied */
-   git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
+   git_xmerge_config("merge.conflictstyle", opts->conflict_style, 
NULL);
}
 
if ((!!opts->new_branch + !!opts->new_branch_force + 
!!opts->new_orphan_branch) > 1)
@@ -1350,7 +1352,7 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
struct object_id rev;
int dwim_ok =
!opts->patch_mode &&
-   dwim_new_local_branch &&
+   opts->dwim_new_local_branch &&
opts->track == BRANCH_TRACK_UNSPECIFIED &&
!opts->new_branch;
int n = parse_branchname_arg(argc, argv, dwim_ok,
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH v3 11/14] switch-branch: only allow explicit detached HEAD

2018-11-29 Thread Nguyễn Thái Ngọc Duy
"git checkout " will checkout the commit in question and
detach HEAD from the current branch. It is naturally a right thing to
do once you get git references. But detached HEAD is a scary concept
to new users because we show a lot of warnings and stuff, and it could
be hard to get out of (until you know better).

To keep switch-branch a bit more friendly to new users, we only allow
entering detached HEAD mode when --detach is given. "git
switch-branch" must take a branch (unless you create a new branch,
then of course switch-branch can take any commit-ish)

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index c7ae068d2c..fbfebba2d9 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -49,6 +49,7 @@ struct checkout_opts {
int merge;
int force;
int force_detach;
+   int implicit_detach;
int writeout_stage;
int overwrite_ignore;
int ignore_skipworktree;
@@ -1241,6 +1242,13 @@ static int checkout_branch(struct checkout_opts *opts,
!opts->force_detach)
die(_("nothing to do"));
 
+   if (!opts->implicit_detach &&
+   !opts->new_branch &&
+   !opts->new_branch_force &&
+   new_branch_info->name &&
+   !new_branch_info->path)
+   die(_("a branch is expected, got %s"), new_branch_info->name);
+
if (new_branch_info->path && !opts->force_detach && !opts->new_branch &&
!opts->ignore_other_worktrees) {
int flag;
@@ -1485,6 +1493,7 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
opts.dwim_new_local_branch = 1;
opts.switch_branch_doing_nothing_not_ok = 0;
opts.accept_pathspec = 1;
+   opts.implicit_detach = 1;
 
options = parse_options_dup(checkout_options);
options = add_common_options(, options);
@@ -1513,6 +1522,7 @@ int cmd_switch_branch(int argc, const char **argv, const 
char *prefix)
opts.dwim_new_local_branch = 1;
opts.accept_pathspec = 0;
opts.switch_branch_doing_nothing_not_ok = 1;
+   opts.implicit_detach = 0;
 
options = parse_options_dup(switch_options);
options = add_common_options(, options);
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH v3 04/14] checkout: make "opts" in cmd_checkout() a pointer

2018-11-29 Thread Nguyễn Thái Ngọc Duy
"opts" will soon be moved out of cmd_checkout(). To keep changes in
that patch smaller, convert "opts" to a pointer and keep the real
thing behind "real_opts".

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 109 +++--
 1 file changed, 55 insertions(+), 54 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 1887c996c6..1b19328d0a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1236,76 +1236,77 @@ static int checkout_branch(struct checkout_opts *opts,
 
 int cmd_checkout(int argc, const char **argv, const char *prefix)
 {
-   struct checkout_opts opts;
+   struct checkout_opts real_opts;
+   struct checkout_opts *opts = _opts;
struct branch_info new_branch_info;
char *conflict_style = NULL;
int dwim_new_local_branch = 1;
int dwim_remotes_matched = 0;
struct option options[] = {
-   OPT__QUIET(, N_("suppress progress reporting")),
-   OPT_STRING('b', NULL, _branch, N_("branch"),
+   OPT__QUIET(>quiet, N_("suppress progress reporting")),
+   OPT_STRING('b', NULL, >new_branch, N_("branch"),
   N_("create and checkout a new branch")),
-   OPT_STRING('B', NULL, _branch_force, N_("branch"),
+   OPT_STRING('B', NULL, >new_branch_force, N_("branch"),
   N_("create/reset and checkout a branch")),
-   OPT_BOOL('l', NULL, _branch_log, N_("create reflog for 
new branch")),
-   OPT_BOOL(0, "detach", _detach, N_("detach HEAD at 
named commit")),
-   OPT_SET_INT('t', "track",  , N_("set upstream info 
for new branch"),
+   OPT_BOOL('l', NULL, >new_branch_log, N_("create reflog 
for new branch")),
+   OPT_BOOL(0, "detach", >force_detach, N_("detach HEAD at 
named commit")),
+   OPT_SET_INT('t', "track",  >track, N_("set upstream info 
for new branch"),
BRANCH_TRACK_EXPLICIT),
-   OPT_STRING(0, "orphan", _orphan_branch, 
N_("new-branch"), N_("new unparented branch")),
-   OPT_SET_INT_F('2', "ours", _stage,
+   OPT_STRING(0, "orphan", >new_orphan_branch, 
N_("new-branch"), N_("new unparented branch")),
+   OPT_SET_INT_F('2', "ours", >writeout_stage,
  N_("checkout our version for unmerged files"),
  2, PARSE_OPT_NONEG),
-   OPT_SET_INT_F('3', "theirs", _stage,
+   OPT_SET_INT_F('3', "theirs", >writeout_stage,
  N_("checkout their version for unmerged files"),
  3, PARSE_OPT_NONEG),
-   OPT__FORCE(, N_("force checkout (throw away local 
modifications)"),
+   OPT__FORCE(>force, N_("force checkout (throw away local 
modifications)"),
   PARSE_OPT_NOCOMPLETE),
-   OPT_BOOL('m', "merge", , N_("perform a 3-way merge 
with the new branch")),
-   OPT_BOOL_F(0, "overwrite-ignore", _ignore,
+   OPT_BOOL('m', "merge", >merge, N_("perform a 3-way merge 
with the new branch")),
+   OPT_BOOL_F(0, "overwrite-ignore", >overwrite_ignore,
   N_("update ignored files (default)"),
   PARSE_OPT_NOCOMPLETE),
OPT_STRING(0, "conflict", _style, N_("style"),
   N_("conflict style (merge or diff3)")),
-   OPT_BOOL('p', "patch", _mode, N_("select hunks 
interactively")),
-   OPT_BOOL(0, "ignore-skip-worktree-bits", 
_skipworktree,
+   OPT_BOOL('p', "patch", >patch_mode, N_("select hunks 
interactively")),
+   OPT_BOOL(0, "ignore-skip-worktree-bits", 
>ignore_skipworktree,
 N_("do not limit pathspecs to sparse entries only")),
OPT_HIDDEN_BOOL(0, "guess", _new_local_branch,
N_("second guess 'git checkout 
'")),
-   OPT_BOOL(0, "ignore-other-worktrees", 
_other_worktrees,
+   OPT_BOOL(0, "ignore-other-worktrees", 
>ignore_other_worktrees,
 N_("do not check if another worktree is holding the 
given ref")),
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL,
"checkout", "control recursive updating of 
submodules",
PARSE_OPT_OPTARG, 
option_parse_recurse_submodules_worktree_updater },
-   OPT_BOOL(0, "progress", _progress, N_("force progress 
reporting")),
+   OPT_BOOL(0, "progress", >show_progress, N_("force 
progress reporting")),
OPT_END(),
};
 
-   memset(, 0, sizeof(opts));
+   memset(opts, 0, sizeof(*opts));
memset(_branch_info, 0, sizeof(new_branch_info));
-   opts.overwrite_ignore = 1;
-   opts.prefix = prefix;
-   

[PATCH v3 02/14] git-checkout.txt: split detached head section out

2018-11-29 Thread Nguyễn Thái Ngọc Duy
This is to be reused by the coming git-switch-branch.txt man page
which also deals with detached HEAD.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/detach-head.txt  | 132 
 Documentation/git-checkout.txt | 133 +
 2 files changed, 133 insertions(+), 132 deletions(-)
 create mode 100644 Documentation/detach-head.txt

diff --git a/Documentation/detach-head.txt b/Documentation/detach-head.txt
new file mode 100644
index 00..bb6f5d7843
--- /dev/null
+++ b/Documentation/detach-head.txt
@@ -0,0 +1,132 @@
+HEAD normally refers to a named branch (e.g. 'master'). Meanwhile, each
+branch refers to a specific commit. Let's look at a repo with three
+commits, one of them tagged, and with branch 'master' checked out:
+
+
+   HEAD (refers to branch 'master')
+|
+v
+a---b---c  branch 'master' (refers to commit 'c')
+^
+|
+  tag 'v2.0' (refers to commit 'b')
+
+
+When a commit is created in this state, the branch is updated to refer to
+the new commit. Specifically, 'git commit' creates a new commit 'd', whose
+parent is commit 'c', and then updates branch 'master' to refer to new
+commit 'd'. HEAD still refers to branch 'master' and so indirectly now refers
+to commit 'd':
+
+
+$ edit; git add; git commit
+
+   HEAD (refers to branch 'master')
+|
+v
+a---b---c---d  branch 'master' (refers to commit 'd')
+^
+|
+  tag 'v2.0' (refers to commit 'b')
+
+
+It is sometimes useful to be able to checkout a commit that is not at
+the tip of any named branch, or even to create a new commit that is not
+referenced by a named branch. Let's look at what happens when we
+checkout commit 'b' (here we show two ways this may be done):
+
+
+$ git checkout v2.0  # or
+$ git checkout master^^
+
+   HEAD (refers to commit 'b')
+|
+v
+a---b---c---d  branch 'master' (refers to commit 'd')
+^
+|
+  tag 'v2.0' (refers to commit 'b')
+
+
+Notice that regardless of which checkout command we use, HEAD now refers
+directly to commit 'b'. This is known as being in detached HEAD state.
+It means simply that HEAD refers to a specific commit, as opposed to
+referring to a named branch. Let's see what happens when we create a commit:
+
+
+$ edit; git add; git commit
+
+ HEAD (refers to commit 'e')
+  |
+  v
+  e
+ /
+a---b---c---d  branch 'master' (refers to commit 'd')
+^
+|
+  tag 'v2.0' (refers to commit 'b')
+
+
+There is now a new commit 'e', but it is referenced only by HEAD. We can
+of course add yet another commit in this state:
+
+
+$ edit; git add; git commit
+
+ HEAD (refers to commit 'f')
+  |
+  v
+  e---f
+ /
+a---b---c---d  branch 'master' (refers to commit 'd')
+^
+|
+  tag 'v2.0' (refers to commit 'b')
+
+
+In fact, we can perform all the normal Git operations. But, let's look
+at what happens when we then checkout master:
+
+
+$ git checkout master
+
+   HEAD (refers to branch 'master')
+  e---f |
+ /  v
+a---b---c---d  branch 'master' (refers to commit 'd')
+^
+|
+  tag 'v2.0' (refers to commit 'b')
+
+
+It is important to realize that at this point nothing refers to commit
+'f'. Eventually commit 'f' (and by extension commit 'e') will be deleted
+by the routine Git garbage collection process, unless we create a reference
+before that happens. If we have not yet moved away from commit 'f',
+any of these will create a reference to it:
+
+
+$ git checkout -b foo   <1>
+$ git branch foo<2>
+$ git tag foo   <3>
+
+
+<1> creates a new branch 'foo', which refers to commit 'f', and then
+updates HEAD to refer to branch 'foo'. In other words, we'll no longer
+be in detached HEAD state after this command.
+
+<2> similarly creates a new branch 'foo', which refers to commit 'f',
+but leaves HEAD detached.
+
+<3> creates a new tag 'foo', which refers to commit 'f',
+leaving HEAD detached.
+
+If we have moved away from commit 'f', then we must first recover its object
+name (typically by using git reflog), and then we can create a reference to
+it. For example, to see the last two commits to which HEAD referred, we
+can use either of these commands:
+
+
+$ git reflog -2 HEAD # or
+$ git log -g -2 HEAD
+
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 65bd1bc50d..25887a6087 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -306,138 +306,7 @@ leave out at most one of `A` and `B`, in which case it 
defaults to `HEAD`.
 
 DETACHED HEAD
 -
-HEAD normally refers to a named branch (e.g. 'master'). Meanwhile, each
-branch refers to a specific commit. Let's look at a repo with 

[PATCH v3 12/14] restore-files: take tree-ish from --from option instead

2018-11-29 Thread Nguyễn Thái Ngọc Duy
This is another departure from 'git checkout' syntax, which uses -- to
separate ref and pathspec. The observation is restore-files (or "git
checkout ,, ") is most often used to restore some files from
the index. If this is correct, we can simplify it by taking a way the
ref, so that we can write

git restore-files some-file

without worrying about some-file being a ref and whether we need to do

git restore-files -- some-file

for safety. If the source of the restore comes from a tree, it will be
in the form of an option with value, e.g.

git restore-files --from=this-tree some-file

This is of course longer to type than using "--". But hopefully it
will not be used as often, and it is clearly easier to understand.

dwim_new_local_branch is no longer set (or unset) in cmd_restore_files()
because it's irrelevant because we don't really care about dwim-ing.
With accept_ref being unset, dwim can't happen.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 41 ++---
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index fbfebba2d9..7ff9951818 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -39,7 +39,7 @@ static const char * const switch_branch_usage[] = {
 };
 
 static const char * const restore_files_usage[] = {
-   N_("git restore-files [] [] -- ..."),
+   N_("git restore-files [] [--from=] ..."),
NULL,
 };
 
@@ -56,6 +56,7 @@ struct checkout_opts {
int ignore_other_worktrees;
int show_progress;
int dwim_new_local_branch;
+   int accept_ref;
int accept_pathspec;
int switch_branch_doing_nothing_not_ok;
 
@@ -75,6 +76,7 @@ struct checkout_opts {
int branch_exists;
const char *prefix;
struct pathspec pathspec;
+   const char *from_treeish;
struct tree *source_tree;
 };
 
@@ -1337,6 +1339,7 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
 {
struct branch_info new_branch_info;
int dwim_remotes_matched = 0;
+   int parseopt_flags = 0;
 
memset(_branch_info, 0, sizeof(new_branch_info));
opts->overwrite_ignore = 1;
@@ -1347,8 +1350,13 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
 
opts->track = BRANCH_TRACK_UNSPECIFIED;
 
-   argc = parse_options(argc, argv, prefix, options, usagestr,
-PARSE_OPT_KEEP_DASHDASH);
+   if (!opts->accept_pathspec && !opts->accept_ref)
+   BUG("make up your mind, you need to take _something_");
+   if (opts->accept_pathspec && opts->accept_ref)
+   parseopt_flags = PARSE_OPT_KEEP_DASHDASH;
+
+   argc = parse_options(argc, argv, prefix, options,
+usagestr, parseopt_flags);
 
if (opts->show_progress < 0) {
if (opts->quiet)
@@ -1402,7 +1410,7 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
 * including "last branch" syntax and DWIM-ery for names of
 * remote branches, erroring out for invalid or ambiguous cases.
 */
-   if (argc) {
+   if (argc && opts->accept_ref && opts->accept_pathspec) {
struct object_id rev;
int dwim_ok =
!opts->patch_mode &&
@@ -1414,6 +1422,18 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
 _remotes_matched);
argv += n;
argc -= n;
+   } else if (!opts->accept_ref && opts->from_treeish) {
+   struct object_id rev;
+
+   if (get_oid_mb(opts->from_treeish, ))
+   die(_("could not resolve %s"), opts->from_treeish);
+
+   setup_new_branch_info_and_source_tree(_branch_info,
+ opts, ,
+ opts->from_treeish);
+
+   if (!opts->source_tree)
+   die(_("reference is not a tree: %s"), 
opts->from_treeish);
}
 
if (argc) {
@@ -1492,6 +1512,7 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
opts.switch_branch_doing_nothing_not_ok = 0;
+   opts.accept_ref = 1;
opts.accept_pathspec = 1;
opts.implicit_detach = 1;
 
@@ -1520,6 +1541,7 @@ int cmd_switch_branch(int argc, const char **argv, const 
char *prefix)
 
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
+   opts.accept_ref = 1;
opts.accept_pathspec = 0;
opts.switch_branch_doing_nothing_not_ok = 1;
opts.implicit_detach = 0;
@@ -1537,14 +1559,19 @@ int cmd_switch_branch(int argc, const char **argv, 
const char *prefix)
 int cmd_restore_files(int argc, const char **argv, const char *prefix)

[PATCH v3 08/14] switch-branch: better names for -b and -B

2018-11-29 Thread Nguyễn Thái Ngọc Duy
The shortcut of these options do not make much sense when used with
switch-branch. And their descriptions are also tied to checkout
out. Move -b/-B to cmd_checkout() and new -c/-C with the same
functionality in cmd_switch_branch()

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 30 +++---
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 7dc0f4d3f3..ceb635de36 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1268,14 +1268,10 @@ static struct option *add_common_options(struct 
checkout_opts *opts,
return newopts;
 }
 
-static struct option *add_switch_branch_options(struct checkout_opts *opts,
-   struct option *prevopts)
+static struct option *add_common_switch_branch_options(
+   struct checkout_opts *opts, struct option *prevopts)
 {
struct option options[] = {
-   OPT_STRING('b', NULL, >new_branch, N_("branch"),
-  N_("create and checkout a new branch")),
-   OPT_STRING('B', NULL, >new_branch_force, N_("branch"),
-  N_("create/reset and checkout a branch")),
OPT_BOOL('l', NULL, >new_branch_log, N_("create reflog 
for new branch")),
OPT_BOOL(0, "detach", >force_detach, N_("detach HEAD at 
named commit")),
OPT_SET_INT('t', "track",  >track, N_("set upstream info 
for new branch"),
@@ -1461,15 +1457,21 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
 int cmd_checkout(int argc, const char **argv, const char *prefix)
 {
struct checkout_opts opts;
-   struct option *options = NULL;
+   struct option *options;
+   struct option checkout_options[] = {
+   OPT_STRING('b', NULL, _branch, N_("branch"),
+  N_("create and checkout a new branch")),
+   OPT_STRING('B', NULL, _branch_force, N_("branch"),
+  N_("create/reset and checkout a branch")),
+   };
int ret;
 
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
 
-   options = parse_options_dup(options);
+   options = parse_options_dup(checkout_options);
options = add_common_options(, options);
-   options = add_switch_branch_options(, options);
+   options = add_common_switch_branch_options(, options);
options = add_checkout_path_options(, options);
 
ret = checkout_main(argc, argv, prefix, ,
@@ -1482,14 +1484,20 @@ int cmd_switch_branch(int argc, const char **argv, 
const char *prefix)
 {
struct checkout_opts opts;
struct option *options = NULL;
+   struct option switch_options[] = {
+   OPT_STRING('c', "create", _branch, N_("branch"),
+  N_("create and switch to a new branch")),
+   OPT_STRING('C', "force-create", _branch_force, 
N_("branch"),
+  N_("create/reset and switch to a new branch")),
+   };
int ret;
 
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
 
-   options = parse_options_dup(options);
+   options = parse_options_dup(switch_options);
options = add_common_options(, options);
-   options = add_switch_branch_options(, options);
+   options = add_common_switch_branch_options(, options);
 
ret = checkout_main(argc, argv, prefix, ,
options, switch_branch_usage);
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH v3 06/14] checkout: split options[] array in three pieces

2018-11-29 Thread Nguyễn Thái Ngọc Duy
This is a preparation step for introducing new commands that do parts
of what checkout does. There will be two new commands, one is about
switching branches, detaching HEAD... one about checking out
paths. These share the a subset of command line options. The rest of
command line options are separate.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 77 +-
 parse-options-cb.c | 16 ++
 parse-options.h|  3 +-
 3 files changed, 73 insertions(+), 23 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 2423fdbf94..764e1a83a1 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1237,14 +1237,31 @@ static int checkout_branch(struct checkout_opts *opts,
return switch_branches(opts, new_branch_info);
 }
 
-int cmd_checkout(int argc, const char **argv, const char *prefix)
+static struct option *add_common_options(struct checkout_opts *opts,
+struct option *prevopts)
 {
-   struct checkout_opts real_opts;
-   struct checkout_opts *opts = _opts;
-   struct branch_info new_branch_info;
-   int dwim_remotes_matched = 0;
struct option options[] = {
OPT__QUIET(>quiet, N_("suppress progress reporting")),
+   { OPTION_CALLBACK, 0, "recurse-submodules", NULL,
+   "checkout", "control recursive updating of 
submodules",
+   PARSE_OPT_OPTARG, 
option_parse_recurse_submodules_worktree_updater },
+   OPT_BOOL(0, "progress", >show_progress, N_("force 
progress reporting")),
+   OPT__FORCE(>force, N_("force checkout (throw away local 
modifications)"),
+  PARSE_OPT_NOCOMPLETE),
+   OPT_BOOL('m', "merge", >merge, N_("perform a 3-way merge 
with the new branch")),
+   OPT_STRING(0, "conflict", >conflict_style, N_("style"),
+  N_("conflict style (merge or diff3)")),
+   OPT_END()
+   };
+   struct option *newopts = parse_options_concat(prevopts, options);
+   free(prevopts);
+   return newopts;
+}
+
+static struct option *add_switch_branch_options(struct checkout_opts *opts,
+   struct option *prevopts)
+{
+   struct option options[] = {
OPT_STRING('b', NULL, >new_branch, N_("branch"),
   N_("create and checkout a new branch")),
OPT_STRING('B', NULL, >new_branch_force, N_("branch"),
@@ -1254,33 +1271,44 @@ int cmd_checkout(int argc, const char **argv, const 
char *prefix)
OPT_SET_INT('t', "track",  >track, N_("set upstream info 
for new branch"),
BRANCH_TRACK_EXPLICIT),
OPT_STRING(0, "orphan", >new_orphan_branch, 
N_("new-branch"), N_("new unparented branch")),
+   OPT_HIDDEN_BOOL(0, "guess", >dwim_new_local_branch,
+   N_("second guess 'git checkout 
'")),
+   OPT_BOOL(0, "ignore-other-worktrees", 
>ignore_other_worktrees,
+N_("do not check if another worktree is holding the 
given ref")),
+   OPT_END()
+   };
+   struct option *newopts = parse_options_concat(prevopts, options);
+   free(prevopts);
+   return newopts;
+}
+
+static struct option *add_checkout_path_options(struct checkout_opts *opts,
+   struct option *prevopts)
+{
+   struct option options[] = {
OPT_SET_INT_F('2', "ours", >writeout_stage,
  N_("checkout our version for unmerged files"),
  2, PARSE_OPT_NONEG),
OPT_SET_INT_F('3', "theirs", >writeout_stage,
  N_("checkout their version for unmerged files"),
  3, PARSE_OPT_NONEG),
-   OPT__FORCE(>force, N_("force checkout (throw away local 
modifications)"),
-  PARSE_OPT_NOCOMPLETE),
-   OPT_BOOL('m', "merge", >merge, N_("perform a 3-way merge 
with the new branch")),
-   OPT_BOOL_F(0, "overwrite-ignore", >overwrite_ignore,
-  N_("update ignored files (default)"),
-  PARSE_OPT_NOCOMPLETE),
-   OPT_STRING(0, "conflict", >conflict_style, N_("style"),
-  N_("conflict style (merge or diff3)")),
OPT_BOOL('p', "patch", >patch_mode, N_("select hunks 
interactively")),
OPT_BOOL(0, "ignore-skip-worktree-bits", 
>ignore_skipworktree,
 N_("do not limit pathspecs to sparse entries only")),
-   OPT_HIDDEN_BOOL(0, "guess", >dwim_new_local_branch,
-   N_("second guess 'git checkout 
'")),
-   OPT_BOOL(0, "ignore-other-worktrees", 
>ignore_other_worktrees,
-  

[PATCH v3 13/14] restore-files: make pathspec mandatory

2018-11-29 Thread Nguyễn Thái Ngọc Duy
"git restore-files" without arguments does not make much sense when
it's about restoring files (what files now?). We could default to
either

git restore-files .

or

git restore-files :/

Neither is intuitive. Make the user always give pathspec, force the
user to think the scope of restore they want.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 7ff9951818..961a90b1c0 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -59,6 +59,7 @@ struct checkout_opts {
int accept_ref;
int accept_pathspec;
int switch_branch_doing_nothing_not_ok;
+   int empty_pathspec_ok;
 
/*
 * If new checkout options are added, skip_merge_working_tree
@@ -1436,6 +1437,9 @@ static int checkout_main(int argc, const char **argv, 
const char *prefix,
die(_("reference is not a tree: %s"), 
opts->from_treeish);
}
 
+   if (opts->accept_pathspec && !opts->empty_pathspec_ok && !argc)
+   die(_("pathspec is required"));
+
if (argc) {
parse_pathspec(>pathspec, 0,
   opts->patch_mode ? PATHSPEC_PREFIX_ORIGIN : 0,
@@ -1515,6 +1519,7 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
opts.accept_ref = 1;
opts.accept_pathspec = 1;
opts.implicit_detach = 1;
+   opts.empty_pathspec_ok = 1;
 
options = parse_options_dup(checkout_options);
options = add_common_options(, options);
@@ -1570,6 +1575,7 @@ int cmd_restore_files(int argc, const char **argv, const 
char *prefix)
memset(, 0, sizeof(opts));
opts.accept_ref = 0;
opts.accept_pathspec = 1;
+   opts.empty_pathspec_ok = 0;
 
options = parse_options_dup(restore_options);
options = add_common_options(, options);
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH v3 09/14] switch-branch: stop accepting pathspec

2018-11-29 Thread Nguyễn Thái Ngọc Duy
This command is about switching branch (or creating a new one) and
should not accept pathspec. This helps simplify ambiguation
handling. The other two ("git checkout" and "git restore-files") of
course do accept pathspec as before.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index ceb635de36..880030e929 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -55,6 +55,7 @@ struct checkout_opts {
int ignore_other_worktrees;
int show_progress;
int dwim_new_local_branch;
+   int accept_pathspec;
 
/*
 * If new checkout options are added, skip_merge_working_tree
@@ -1089,10 +1090,16 @@ static int parse_branchname_arg(int argc, const char 
**argv,
if (!argc)
return 0;
 
+   if (!opts->accept_pathspec) {
+   if (argc > 1)
+   die(_("only one reference expected"));
+   has_dash_dash = 1; /* helps disambiguate */
+   }
+
arg = argv[0];
dash_dash_pos = -1;
for (i = 0; i < argc; i++) {
-   if (!strcmp(argv[i], "--")) {
+   if (opts->accept_pathspec && !strcmp(argv[i], "--")) {
dash_dash_pos = i;
break;
}
@@ -1167,7 +1174,7 @@ static int parse_branchname_arg(int argc, const char 
**argv,
 */
if (argc)
verify_non_filename(opts->prefix, arg);
-   } else {
+   } else if (opts->accept_pathspec) {
argcount++;
argv++;
argc--;
@@ -1468,6 +1475,7 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
 
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
+   opts.accept_pathspec = 1;
 
options = parse_options_dup(checkout_options);
options = add_common_options(, options);
@@ -1494,6 +1502,7 @@ int cmd_switch_branch(int argc, const char **argv, const 
char *prefix)
 
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
+   opts.accept_pathspec = 0;
 
options = parse_options_dup(switch_options);
options = add_common_options(, options);
@@ -1513,6 +1522,7 @@ int cmd_restore_files(int argc, const char **argv, const 
char *prefix)
 
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
+   opts.accept_pathspec = 1;
 
options = parse_options_dup(options);
options = add_common_options(, options);
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH v3 03/14] checkout: factor out some code in parse_branchname_arg()

2018-11-29 Thread Nguyễn Thái Ngọc Duy
This is in preparation for the new command restore-files, which also
needs to parse opts->source_tree but does not need all the
disambiguation logic.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 51 --
 1 file changed, 31 insertions(+), 20 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index acdafc6e4c..1887c996c6 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -990,6 +990,34 @@ static int git_checkout_config(const char *var, const char 
*value, void *cb)
return git_xmerge_config(var, value, NULL);
 }
 
+static void setup_new_branch_info_and_source_tree(
+   struct branch_info *new_branch_info,
+   struct checkout_opts *opts,
+   struct object_id *rev,
+   const char *arg)
+{
+   struct tree **source_tree = >source_tree;
+   struct object_id branch_rev;
+
+   new_branch_info->name = arg;
+   setup_branch_path(new_branch_info);
+
+   if (!check_refname_format(new_branch_info->path, 0) &&
+   !read_ref(new_branch_info->path, _rev))
+   oidcpy(rev, _rev);
+   else
+   new_branch_info->path = NULL; /* not an existing branch */
+
+   new_branch_info->commit = 
lookup_commit_reference_gently(the_repository, rev, 1);
+   if (!new_branch_info->commit) {
+   /* not a commit */
+   *source_tree = parse_tree_indirect(rev);
+   } else {
+   parse_commit_or_die(new_branch_info->commit);
+   *source_tree = get_commit_tree(new_branch_info->commit);
+   }
+}
+
 static int parse_branchname_arg(int argc, const char **argv,
int dwim_new_local_branch_ok,
struct branch_info *new_branch_info,
@@ -997,10 +1025,8 @@ static int parse_branchname_arg(int argc, const char 
**argv,
struct object_id *rev,
int *dwim_remotes_matched)
 {
-   struct tree **source_tree = >source_tree;
const char **new_branch = >new_branch;
int argcount = 0;
-   struct object_id branch_rev;
const char *arg;
int dash_dash_pos;
int has_dash_dash = 0;
@@ -1114,26 +1140,11 @@ static int parse_branchname_arg(int argc, const char 
**argv,
argv++;
argc--;
 
-   new_branch_info->name = arg;
-   setup_branch_path(new_branch_info);
-
-   if (!check_refname_format(new_branch_info->path, 0) &&
-   !read_ref(new_branch_info->path, _rev))
-   oidcpy(rev, _rev);
-   else
-   new_branch_info->path = NULL; /* not an existing branch */
+   setup_new_branch_info_and_source_tree(new_branch_info, opts, rev, arg);
 
-   new_branch_info->commit = 
lookup_commit_reference_gently(the_repository, rev, 1);
-   if (!new_branch_info->commit) {
-   /* not a commit */
-   *source_tree = parse_tree_indirect(rev);
-   } else {
-   parse_commit_or_die(new_branch_info->commit);
-   *source_tree = get_commit_tree(new_branch_info->commit);
-   }
-
-   if (!*source_tree)   /* case (1): want a tree */
+   if (!opts->source_tree)   /* case (1): want a tree */
die(_("reference is not a tree: %s"), arg);
+
if (!has_dash_dash) {   /* case (3).(d) -> (1) */
/*
 * Do not complain the most common case
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH v3 07/14] checkout: split into switch-branch and restore-files

2018-11-29 Thread Nguyễn Thái Ngọc Duy
"git checkout" doing too many things is a source of confusion for many
users (and it even bites old timers sometimes). To rememdy that, the
command is now split in two: switch-branch and checkout-files. The
good old "git checkout" command is still here and will be until all
(or most of users) are sick of it.

See the new man pages for the final design of these commands. The
actual implementation though is still pretty much the same as "git
checkout". Following patches will adjust their behavior to match the
man pages.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 .gitignore  |   2 +
 Documentation/git-checkout.txt  |   5 +
 Documentation/git-restore-files.txt | 167 
 Documentation/git-switch-branch.txt | 289 
 Makefile|   2 +
 builtin.h   |   2 +
 builtin/checkout.c  |  84 ++--
 command-list.txt|   2 +
 git.c   |   2 +
 9 files changed, 543 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/git-restore-files.txt
 create mode 100644 Documentation/git-switch-branch.txt

diff --git a/.gitignore b/.gitignore
index 0d77ea5894..c63dcb1427 100644
--- a/.gitignore
+++ b/.gitignore
@@ -143,6 +143,7 @@
 /git-request-pull
 /git-rerere
 /git-reset
+/git-restore-files
 /git-rev-list
 /git-rev-parse
 /git-revert
@@ -167,6 +168,7 @@
 /git-submodule
 /git-submodule--helper
 /git-svn
+/git-switch-branch
 /git-symbolic-ref
 /git-tag
 /git-unpack-file
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 25887a6087..25ec7f508f 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -406,6 +406,11 @@ $ edit frotz
 $ git add frotz
 
 
+SEE ALSO
+
+linkgit:git-switch-branch[1]
+linkgit:git-restore-files[1]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-restore-files.txt 
b/Documentation/git-restore-files.txt
new file mode 100644
index 00..03c1250ad0
--- /dev/null
+++ b/Documentation/git-restore-files.txt
@@ -0,0 +1,167 @@
+git-restore-files(1)
+
+
+NAME
+
+git-restore-files - Restore working tree files
+
+SYNOPSIS
+
+[verse]
+'git restore-files' 

[PATCH v3 10/14] switch-branch: reject "do nothing" case

2018-11-29 Thread Nguyễn Thái Ngọc Duy
"git checkout" can be executed without any arguments. What it does is
not exactly great: it switches from HEAD to HEAD and showing worktree
modification as a side effect.

Make switch-branch reject this case. You have to either

- really switch a branch
- (explicitly) detach from the current branch
- create a new branch

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 880030e929..c7ae068d2c 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -56,6 +56,7 @@ struct checkout_opts {
int show_progress;
int dwim_new_local_branch;
int accept_pathspec;
+   int switch_branch_doing_nothing_not_ok;
 
/*
 * If new checkout options are added, skip_merge_working_tree
@@ -1233,6 +1234,13 @@ static int checkout_branch(struct checkout_opts *opts,
die(_("Cannot switch branch to a non-commit '%s'"),
new_branch_info->name);
 
+   if (opts->switch_branch_doing_nothing_not_ok &&
+   !new_branch_info->name &&
+   !opts->new_branch &&
+   !opts->new_branch_force &&
+   !opts->force_detach)
+   die(_("nothing to do"));
+
if (new_branch_info->path && !opts->force_detach && !opts->new_branch &&
!opts->ignore_other_worktrees) {
int flag;
@@ -1475,6 +1483,7 @@ int cmd_checkout(int argc, const char **argv, const char 
*prefix)
 
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
+   opts.switch_branch_doing_nothing_not_ok = 0;
opts.accept_pathspec = 1;
 
options = parse_options_dup(checkout_options);
@@ -1503,6 +1512,7 @@ int cmd_switch_branch(int argc, const char **argv, const 
char *prefix)
memset(, 0, sizeof(opts));
opts.dwim_new_local_branch = 1;
opts.accept_pathspec = 0;
+   opts.switch_branch_doing_nothing_not_ok = 1;
 
options = parse_options_dup(switch_options);
options = add_common_options(, options);
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH v3 01/14] git-checkout.txt: fix one syntax line

2018-11-29 Thread Nguyễn Thái Ngọc Duy
 can be omitted in this syntax, and it's actually documented a
few paragraphs down:

  You could omit , in which case the command degenerates to
  "check out the current branch", which is a glorified no-op with
  rather expensive side-effects to show only the tracking information,
  if exists, for the current branch.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/git-checkout.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 801de2f764..65bd1bc50d 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -23,7 +23,7 @@ or the specified tree.  If no paths are given, 'git checkout' 
will
 also update `HEAD` to set the specified branch as the current
 branch.
 
-'git checkout' ::
+'git checkout' []::
To prepare for working on , switch to it by updating
the index and the files in the working tree, and by pointing
HEAD at the branch. Local modifications to the files in the
-- 
2.20.0.rc1.380.g3eb999425c.dirty



[PATCH/RFC v3 00/14] Introduce new commands switch-branch and restore-files

2018-11-29 Thread Nguyễn Thái Ngọc Duy
v3 sees switch-branch go back to switch-branch (in v2 it was
checkout-branch). checkout-files is also renamed restore-files (v1 was
restore-paths). Hopefully we won't see another rename.

I'll try to summarize the differences between the new commands and
'git checkout' down here, but you're welcome to just head to 07/14 and
read the new man pages.

'git switch-branch'

- does not "do nothing", you have to either switch branch, create a
  new branch, or detach. "git switch-branch" with no arguments is
  rejected.

- implicit detaching is rejected. If you need to detach, you need to
  give --detach. Or stick to 'git checkout'.

- -b/-B is renamed to -c/-C with long option names

- of course does not accept pathspec

'git restore-files'

- takes a ref from --from argument, not as a free ref. As a result,
  '--' is no longer needed. All non-option arguments are pathspec

- pathspec is mandatory, you can't do "git restore-files" without any
  pathspec.

- I just remember -p which is allowed to take no pathspec :( I'll fix
  it later.

- Two more fancy features (the "git checkout --index" being the
  default mode and the backup log for accidental overwrites) are of
  course still missing. But they are coming.

I did not go replace "detached HEAD" with "unnamed branch" (or "no
branch") everywhere because I think a unique term is still good to
refer to this concept. Or maybe "no branch" is good enough. I dunno.

Nguyễn Thái Ngọc Duy (14):
  git-checkout.txt: fix one syntax line
  git-checkout.txt: split detached head section out
  checkout: factor out some code in parse_branchname_arg()
  checkout: make "opts" in cmd_checkout() a pointer
  checkout: move 'confict_style' and 'dwim_..' to checkout_opts
  checkout: split options[] array in three pieces
  checkout: split into switch-branch and restore-files
  switch-branch: better names for -b and -B
  switch-branch: stop accepting pathspec
  switch-branch: reject "do nothing" case
  switch-branch: only allow explicit detached HEAD
  restore-files: take tree-ish from --from option instead
  restore-files: make pathspec mandatory
  doc: promote "git switch-branch" and "git restore-files"

 .gitignore |   2 +
 Documentation/config/advice.txt|  10 +-
 Documentation/config/checkout.txt  |   5 +-
 Documentation/detach-head.txt  | 132 +
 Documentation/git-branch.txt   |   8 +-
 Documentation/git-check-ref-format.txt |   2 +-
 Documentation/git-checkout.txt | 140 +
 Documentation/git-format-patch.txt |   2 +-
 Documentation/git-merge-base.txt   |   2 +-
 Documentation/git-rebase.txt   |   2 +-
 Documentation/git-remote.txt   |   2 +-
 Documentation/git-rerere.txt   |  10 +-
 Documentation/git-reset.txt|  18 +-
 Documentation/git-restore-files.txt| 167 +++
 Documentation/git-revert.txt   |   2 +-
 Documentation/git-stash.txt|   6 +-
 Documentation/git-switch-branch.txt| 289 +++
 Documentation/gitattributes.txt|   2 +-
 Documentation/gitcli.txt   |   4 +-
 Documentation/gitcore-tutorial.txt |  18 +-
 Documentation/giteveryday.txt  |  24 +-
 Documentation/githooks.txt |   5 +-
 Documentation/gittutorial-2.txt|   2 +-
 Documentation/gittutorial.txt  |   4 +-
 Documentation/revisions.txt|   2 +-
 Documentation/user-manual.txt  |  54 ++--
 Makefile   |   2 +
 advice.c   |  11 +-
 builtin.h  |   2 +
 builtin/checkout.c | 380 ++---
 command-list.txt   |   4 +-
 git.c  |   2 +
 parse-options-cb.c |  16 ++
 parse-options.h|   3 +-
 sha1-name.c|   2 +-
 wt-status.c|   2 +-
 36 files changed, 1006 insertions(+), 332 deletions(-)
 create mode 100644 Documentation/detach-head.txt
 create mode 100644 Documentation/git-restore-files.txt
 create mode 100644 Documentation/git-switch-branch.txt

-- 
2.20.0.rc1.380.g3eb999425c.dirty



Re: [PATCH v2 6/7] checkout: split into switch-branch and checkout-files

2018-11-29 Thread Stefan Xenos
>
> Which brings us back to your "git checkout-files " use case
> above. It should be treat the same way in my opinion, so we either do
>
>  git checkout-files --from=tree-ish :/
>
> or
>
>  git checkout-files --from=tree-ish .
>
> But "git checkout-files --from=tree-ish" alone is rejected.

Agreed. Those arguments are better. The gist of my comment was the
treatment of newly created local files rather than the form of the
arguments, but it sounds like you've got that under control, too.

> > Suggestion:
> > If git checkout-files overwrites or deletes any locally-modified files
> > from the workspace or index, those files could be auto-stashed. That
> > would make it easy to restore them in the event of a mistyped command.
> > Auto-stashing could be suppressed with a command-line argument (with
> > alternate behaviors being fail-if-modified or always-overwrite).
>
> Stashing I think is not the right tool for this. When you stash, you
> plan to retrieve it back later but here you should rarely ever need to
> unstash until the accident. For recovery from accidents like this, I
> have another thing in queue to achieve the same (I'm calling it
> "backup log" now). So we will have the same functionality, just with
> different means.

Yes, this makes sense too. You wouldn't want to pollute the stash list
with autogenerated things the user probably doesn't want.

> This one is tricky because we should deal with submodule autoupdate
> consistently across all porcelain commands (or at least common ones),
> not just checkout-files.

This is also a good point. I'd like it if submodules just behaved like
a single giant repository for most commands, but you're right that
this is something that should be done intentionally for all the
commands at one rather than just for a single command.

I also like your new names "switch-branch" and "restore-files".


[PATCH 1/1] rebase: fix GIT_REFLOG_ACTION regression

2018-11-29 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

The scripted version (partially) heeded the `GIT_REFLOG_ACTION` and when
we converted to a built-in, this regressed.

Fix that, and add a regression test, both with `GIT_REFLOG_ACTION` set
and unset.

Note: the reflog message for "rebase finished" did *not* heed
GIT_REFLOG_ACTION, and as we are very late in the v2.20.0-rcN phase, we
leave that bug for later (as it seems that that bug has been with us
from the very beginning).

Reported by Ian Jackson.

Signed-off-by: Johannes Schindelin 
---
 builtin/rebase.c  | 29 ++---
 t/t3406-rebase-message.sh | 26 ++
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5b3e5baec8..ba0c3c954b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -776,6 +776,23 @@ static void NORETURN 
error_on_missing_default_upstream(void)
exit(1);
 }
 
+static void set_reflog_action(struct rebase_options *options)
+{
+   const char *env;
+   struct strbuf buf = STRBUF_INIT;
+
+   if (!is_interactive(options))
+   return;
+
+   env = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
+   if (env && strcmp("rebase", env))
+   return; /* only override it if it is "rebase" */
+
+   strbuf_addf(, "rebase -i (%s)", options->action);
+   setenv(GIT_REFLOG_ACTION_ENVIRONMENT, buf.buf, 1);
+   strbuf_release();
+}
+
 int cmd_rebase(int argc, const char **argv, const char *prefix)
 {
struct rebase_options options = {
@@ -978,6 +995,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
 
if (action != NO_ACTION && !in_progress)
die(_("No rebase in progress?"));
+   setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
 
if (action == ACTION_EDIT_TODO && !is_interactive())
die(_("The --edit-todo action can only be used during "
@@ -990,6 +1008,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
int fd;
 
options.action = "continue";
+   set_reflog_action();
 
/* Sanity check */
if (get_oid("HEAD", ))
@@ -1018,6 +1037,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
struct string_list merge_rr = STRING_LIST_INIT_DUP;
 
options.action = "skip";
+   set_reflog_action();
 
rerere_clear(_rr);
string_list_clear(_rr, 1);
@@ -1033,6 +1053,7 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
case ACTION_ABORT: {
struct string_list merge_rr = STRING_LIST_INIT_DUP;
options.action = "abort";
+   set_reflog_action();
 
rerere_clear(_rr);
string_list_clear(_rr, 1);
@@ -1440,11 +1461,12 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
}
 
strbuf_reset();
-   strbuf_addf(, "rebase: checkout %s",
+   strbuf_addf(, "%s: checkout %s",
+   
getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
options.switch_to);
if (reset_head(, "checkout",
   options.head_name, 0,
-  NULL, NULL) < 0) {
+  NULL, buf.buf) < 0) {
ret = !!error(_("could not switch to "
"%s"),
  options.switch_to);
@@ -1508,7 +1530,8 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
printf(_("First, rewinding head to replay your work on top of "
 "it...\n"));
 
-   strbuf_addf(, "rebase: checkout %s", options.onto_name);
+   strbuf_addf(, "%s: checkout %s",
+   getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
if (reset_head(>object.oid, "checkout", NULL,
   RESET_HEAD_DETACH, NULL, msg.buf))
die(_("Could not detach HEAD"));
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 38bd876cab..db8505eb86 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -91,4 +91,30 @@ test_expect_success 'error out early upon -C or 
--whitespace=' '
test_i18ngrep "Invalid whitespace option" err
 '
 
+test_expect_success 'GIT_REFLOG_ACTION' '
+   git checkout start &&
+   test_commit reflog-onto &&
+   git checkout -b reflog-topic start &&
+   test_commit reflog-to-rebase &&
+
+   git rebase reflog-onto &&
+   git log -g --format=%gs -3 >actual &&
+   cat >expect <<-\EOF &&
+   rebase finished: 

[PATCH 0/1] Fix built-in rebase regression noticed by Debian's dgit

2018-11-29 Thread Johannes Schindelin via GitGitGadget
It has been reported on the Debian bug tracker
[https://bugs.debian.org/914695] that the built-in rebase regresses on the
scripted version, and later details emerged that this has something to do
with the reflog messages: they were different with the built-in rebase than
with the scripted one.

This here patch fixes that.

Johannes Schindelin (1):
  rebase: fix GIT_REFLOG_ACTION regression

 builtin/rebase.c  | 29 ++---
 t/t3406-rebase-message.sh | 26 ++
 2 files changed, 52 insertions(+), 3 deletions(-)


base-commit: 7068cbc4abac53d9c3675dfba81c1e97d25e8eeb
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-91%2Fdscho%2Ffix-reflog-action-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-91/dscho/fix-reflog-action-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/91
-- 
gitgitgadget


Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Johannes Schindelin
Hi Ævar,

On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:

> On Thu, Nov 29 2018, Johannes Schindelin wrote:
> 
> > On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
> >
> >> On Thu, Nov 29 2018, Johannes Schindelin wrote:
> >>
> >> > On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
> >> >
> >> >> On Thu, Nov 29 2018, Johannes Schindelin wrote:
> >> >>
> >> >> > On Wed, 28 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
> >> >> >
> >> >> >> Change the semantics of the "--range-diff" option so that the regular
> >> >> >> diff options can be provided separately for the range-diff and the
> >> >> >> patch. This allows for supplying e.g. --range-diff-U0 and -U1 to
> >> >> >> "format-patch" to provide different context for the range-diff and 
> >> >> >> the
> >> >> >> patch. This wasn't possible before.
> >> >> >
> >> >> > I really, really dislike the `--range-diff-`. We have
> >> >> > precedent for passing optional arguments that are passed to some other
> >> >> > command, so a much more logical and consistent convention would be to 
> >> >> > use
> >> >> > `--range-diff[=..]`, allowing all of the diff options 
> >> >> > that
> >> >> > you might want to pass to the outer diff in one go rather than having 
> >> >> > a
> >> >> > lengthy string of `--range-diff-this` and `--range-diff-that` options.
> >> >>
> >> >> Where do we pass those sorts of arguments?
> >> >>
> >> >> Reasons I did it this way:
> >> >>
> >> >>  a) Passing it as one option will require the user to double-quote those
> >> >> options that take quoted arguments (e.g. --word-diff-regex), which I
> >> >> thought sucked more than the prefix. On the implementation side we
> >> >> couldn't leave the parsing of the command-line to the shell anymore.
> >> >>
> >> >>  b) I think people will want to tweak this very rarely, much more rarely
> >> >> than e.g. -U10 in format-patch itself, so having something long-ish
> >> >> doesn't sound bad.
> >> >
> >> > Hmm. I still don't like it. It sets a precedent, and we simply do not do
> >> > it that way in other circumstances (most obvious would be the -X merge
> >> > options). The more divergent user interfaces for the same sort of thing
> >> > are, the more brain cycles you force users to spend on navigating said
> >> > interfaces.
> >>
> >> Yeah it sucks, I just think it sucks less than the alternative :)
> >> I.e. I'm not picky about --range-diff-* prefix the name, but I think
> >> doing our own shell parsing would be nasty.
> >
> > What prevents you from using `sq_dequote_to_argv()`?
> 
> I mean not just nasty in terms of implementation, yeah we could do it,
> but also a nasty UX for things like --word-diff-regex. I.e. instead of:
> 
> --range-diff-word-diff-regex='[0-9"]'
> 
> You need:
> 
> --range-diff-opts="--word-diff-regex='[0-9\"]'"

Really? I think that would not work. It would pass the single quotes as
part of the regex to the diff machinery.

Or maybe not. But the extra quotes do not strike me as necessary, as there
is no shell script involved (thank deity!) after `git range-diff` parsed
the options.

> Now admittedly that in itself isn't very painful *in this case*, but in
> terms of precedent I really dislike that option, i.e. git having some
> mode where I need to work to escape input to pass to another command.
> 
> Not saying that this --range-diff-* thing is what we should go for, but
> surely we can find some way to do deal with this that doesn't involve
> the user needing to escape stuff like this.
> 
> It also has other downstream effects in the UI, e.g. it's presumably
> easy to teach the bash completion that a --foo=XYZ option is also called
> --some-prefix--foo=XYZ and to enable completion for that, less so for
> making it smart enough to complete "--some-prefix-opts="--foo=".

These are all good points, and need proper discussion.

Sadly, all that time needed for a proper discussion is not left before
v2.20.0 is supposed to come out.

Quite honestly, I think what we will have to do is to describe in the
documentation of `format-patch`'s `--range-diff` option that the exact
user interface how to pass diff options down to `range-diff` is in flux
and not final.

That way, we can give your design the proper treatment, and work together
on making a user interface we all can be happy with.

Ciao,
Dscho

Re: [PATCH v2 6/7] checkout: split into switch-branch and checkout-files

2018-11-29 Thread Duy Nguyen
On Thu, Nov 29, 2018 at 7:14 PM Stefan Beller  wrote:
>
> > > Idea:
> > > If git checkout-files modifies the submodules file, it could also
> > > auto-update the submodules. (For example, with something like "git
> > > submodule update --init --recursive --progress").
> >
> > This one is tricky because we should deal with submodule autoupdate
> > consistently across all porcelain commands (or at least common ones),
> > not just checkout-files. I'd prefer to delay this until later. Once we
> > figure out what to do with other commands, then we can still change
> > defaults for checkout-files.
>
> checkout/reset are respecting the submodule.recurse setting for this
> already, and as your patches only change the UX frontend
>
> git -c submodule.recurse checkout-files 
>
> would also touch submodules. Given that deep down in
> the submodules it's all about files again, we could think
> checkout-files is still a good name.
>
> I think Stefan X. is asking for making submodule.recurse
> to default to true, which is indeed unrelated to this.

Yes and I'm concerned that checkout-files now recurses into submodules
this by default but grep for example does not. That just adds more
confusion.
-- 
Duy


Re: [PATCH v2 6/7] checkout: split into switch-branch and checkout-files

2018-11-29 Thread Stefan Beller
> > Idea:
> > If git checkout-files modifies the submodules file, it could also
> > auto-update the submodules. (For example, with something like "git
> > submodule update --init --recursive --progress").
>
> This one is tricky because we should deal with submodule autoupdate
> consistently across all porcelain commands (or at least common ones),
> not just checkout-files. I'd prefer to delay this until later. Once we
> figure out what to do with other commands, then we can still change
> defaults for checkout-files.

checkout/reset are respecting the submodule.recurse setting for this
already, and as your patches only change the UX frontend

git -c submodule.recurse checkout-files 

would also touch submodules. Given that deep down in
the submodules it's all about files again, we could think
checkout-files is still a good name.

I think Stefan X. is asking for making submodule.recurse
to default to true, which is indeed unrelated to this.

Stefan


Security Alert. git@vger.kernel.org has password ani420. Password must be changed.

2018-11-29 Thread davidb
Hello!

I have very bad news for you.
09/08/2018 - on this day I hacked your OS and got full access to your account 
git@vger.kernel.org
On this day your account git@vger.kernel.org has password: ani420

So, you can change the password, yes.. But my malware intercepts it every time.

How I made it:
In the software of the router, through which you went online, was a 
vulnerability.
I just hacked this router and placed my malicious code on it.
When you went online, my trojan was installed on the OS of your device.

After that, I made a full dump of your disk (I have all your address book, 
history of viewing sites, all files, phone numbers and addresses of all your 
contacts).

A month ago, I wanted to lock your device and ask for a not big amount of btc 
to unlock.
But I looked at the sites that you regularly visit, and I was shocked by what I 
saw!!!
I'm talk you about sites for adults.

I want to say - you are a BIG pervert. Your fantasy is shifted far away from 
the normal course!

And I got an idea
I made a screenshot of the adult sites where you have fun (do you understand 
what it is about, huh?).
After that, I made a screenshot of your joys (using the camera of your device) 
and glued them together.
Turned out amazing! You are so spectacular!

I'm know that you would not like to show these screenshots to your friends, 
relatives or colleagues.
I think $756 is a very, very small amount for my silence.
Besides, I have been spying on you for so long, having spent a lot of time!

Pay ONLY in Bitcoins!
My BTC wallet: 1HkKgPbcMyfhrdPsbufTFczzVnhyT5snB3

You do not know how to use bitcoins?
Enter a query in any search engine: "how to replenish btc wallet".
It's extremely easy

For this payment I give you two days (48 hours).
As soon as this letter is opened, the timer will work.

After payment, my virus and dirty screenshots with your enjoys will be 
self-destruct automatically.
If I do not receive from you the specified amount, then your device will be 
locked, and all your contacts will receive a screenshots with your "enjoys".

I hope you understand your situation.
- Do not try to find and destroy my virus! (All your data, files and 
screenshots is already uploaded to a remote server)
- Do not try to contact me (you yourself will see that this is impossible, the 
sender address is automatically generated)
- Various security services will not help you; formatting a disk or destroying 
a device will not help, since your data is already on a remote server.

P.S. You are not my single victim. so, I guarantee you that I will not disturb 
you again after payment!
 This is the word of honor hacker

I also ask you to regularly update your antiviruses in the future. This way you 
will no longer fall into a similar situation.

Do not hold evil! I just do my job.
Good luck.



Re: [PATCH] rebase: mark the C reimplementation as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)

2018-11-29 Thread Ian Jackson
Johannes Schindelin writes ("Re: [PATCH] rebase: mark the C reimplementation as 
an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)"):
> I'll have to take a (lengthy) dinner break now, but this is what I have so
> far: a regression test that verifies the breakage (see the
> `fix-reflog-action` branch at https://github.com/dscho/git). I'll continue
> after dinner and am confident that this bug will be fixed within the next
> four hours.

That seems super speedy to me!

When you have a fix I will leave it up to the Debian git maintainers
to decide whether they want to cherry pick your fix into their
package, or await an updated upstream branch with rc, or what.

> [Ian:]
> > While you're looking at this, I observe that the fact that the `rebase
> > finished' message also does not honour GIT_REFLOG_ACTION appears to be
> > a pre-existing bug.
> 
> I noticed that, too, but at this point I am only fixing regressions. We
> can try to fix this long-standing bug in the v2.20 cycle.

Right.

Thanks,
Ian.

-- 
Ian JacksonThese opinions are my own.

If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
a private address which bypasses my fierce spamfilter.


Re: [PATCH] rebase: mark the C reimplementation as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)

2018-11-29 Thread Johannes Schindelin
Hi Ian,

On Thu, 29 Nov 2018, Ian Jackson wrote:

> Johannes Schindelin writes ("Re: [PATCH] rebase: mark the C reimplementation 
> as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)"):
> > >  In a successful run with older git I get a reflog like this:
> > > 
> > >4833d74 HEAD@{0}: rebase finished: returning to 
> > > refs/heads/with-preexisting
> > >4833d74 HEAD@{1}: debrebase new-upstream 2.1-1: rebase: Add another 
> > > new upstream file
> > >cabd5ec HEAD@{2}: debrebase new-upstream 2.1-1: rebase: Edit the .c 
> > > file
> > >0b362ce HEAD@{3}: debrebase new-upstream 2.1-1: rebase: Add a new 
> > > upstream file
> > >29653e5 HEAD@{4}: debrebase new-upstream 2.1-1: rebase: checkout 
> > > 29653e5a17bee4ac23a68bba3e12bc1f52858ac3
> > >85e0c46 HEAD@{5}: debrebase: launder for new upstream
> ...
> > >  This breaks the test because my test suite is checking that I set
> > >  GIT_REFLOG_ACTION appropriately.
> > > 
> > >  If you want I can provide a minimal test case but this should suffice
> > >  to see the bug I hope...
> > 
> > This should be plenty for me to get going. Thank you!
> 
> Happy hunting.

I'll have to take a (lengthy) dinner break now, but this is what I have so
far: a regression test that verifies the breakage (see the
`fix-reflog-action` branch at https://github.com/dscho/git). I'll continue
after dinner and am confident that this bug will be fixed within the next
four hours.

> While you're looking at this, I observe that the fact that the `rebase
> finished' message also does not honour GIT_REFLOG_ACTION appears to be
> a pre-existing bug.

I noticed that, too, but at this point I am only fixing regressions. We
can try to fix this long-standing bug in the v2.20 cycle.

Ciao,
Johannes

> (In general one often can't rely on GIT_REFLOG_ACTION still being set
> because the rebase might have been interrupted and restarted, which I
> think is why my test case looks for it in the initial `checkout'
> message.)
> 
> Regards,
> Ian.
> 
> -- 
> Ian JacksonThese opinions are my own.
> 
> If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
> a private address which bypasses my fierce spamfilter.
> 


Re: [PATCH] pack-protocol.txt: accept error packets in any context

2018-11-29 Thread Masaya Suzuki
On Thu, Nov 29, 2018 at 3:42 AM Junio C Hamano  wrote:
>
> Masaya Suzuki  writes:
>
> > In the Git pack protocol definition, an error packet may appear only in
> > a certain context. However, servers can face a runtime error (e.g. I/O
> > error) at an arbitrary timing. This patch changes the protocol to allow
> > an error packet to be sent instead of any packet.
> >
> > Following this protocol spec change, the error packet handling code is
> > moved to pkt-line.c.
> >
> > Signed-off-by: Masaya Suzuki 
> > ---
>
> Have you run tests with this applied?  I noticed 5703.9 now has
> stale expectations, but there may be others.

Yes, I did. And it also didn't end up in a build error. Do I have a
different build option...?


Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Thu, Nov 29 2018, Johannes Schindelin wrote:

> Hi Ævar,
>
> On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
>
>> On Thu, Nov 29 2018, Johannes Schindelin wrote:
>>
>> > On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
>> >
>> >> On Thu, Nov 29 2018, Johannes Schindelin wrote:
>> >>
>> >> > On Wed, 28 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
>> >> >
>> >> >> Change the semantics of the "--range-diff" option so that the regular
>> >> >> diff options can be provided separately for the range-diff and the
>> >> >> patch. This allows for supplying e.g. --range-diff-U0 and -U1 to
>> >> >> "format-patch" to provide different context for the range-diff and the
>> >> >> patch. This wasn't possible before.
>> >> >
>> >> > I really, really dislike the `--range-diff-`. We have
>> >> > precedent for passing optional arguments that are passed to some other
>> >> > command, so a much more logical and consistent convention would be to 
>> >> > use
>> >> > `--range-diff[=..]`, allowing all of the diff options that
>> >> > you might want to pass to the outer diff in one go rather than having a
>> >> > lengthy string of `--range-diff-this` and `--range-diff-that` options.
>> >>
>> >> Where do we pass those sorts of arguments?
>> >>
>> >> Reasons I did it this way:
>> >>
>> >>  a) Passing it as one option will require the user to double-quote those
>> >> options that take quoted arguments (e.g. --word-diff-regex), which I
>> >> thought sucked more than the prefix. On the implementation side we
>> >> couldn't leave the parsing of the command-line to the shell anymore.
>> >>
>> >>  b) I think people will want to tweak this very rarely, much more rarely
>> >> than e.g. -U10 in format-patch itself, so having something long-ish
>> >> doesn't sound bad.
>> >
>> > Hmm. I still don't like it. It sets a precedent, and we simply do not do
>> > it that way in other circumstances (most obvious would be the -X merge
>> > options). The more divergent user interfaces for the same sort of thing
>> > are, the more brain cycles you force users to spend on navigating said
>> > interfaces.
>>
>> Yeah it sucks, I just think it sucks less than the alternative :)
>> I.e. I'm not picky about --range-diff-* prefix the name, but I think
>> doing our own shell parsing would be nasty.
>
> What prevents you from using `sq_dequote_to_argv()`?

I mean not just nasty in terms of implementation, yeah we could do it,
but also a nasty UX for things like --word-diff-regex. I.e. instead of:

--range-diff-word-diff-regex='[0-9"]'

You need:

--range-diff-opts="--word-diff-regex='[0-9\"]'"

Now admittedly that in itself isn't very painful *in this case*, but in
terms of precedent I really dislike that option, i.e. git having some
mode where I need to work to escape input to pass to another command.

Not saying that this --range-diff-* thing is what we should go for, but
surely we can find some way to do deal with this that doesn't involve
the user needing to escape stuff like this.

It also has other downstream effects in the UI, e.g. it's presumably
easy to teach the bash completion that a --foo=XYZ option is also called
--some-prefix--foo=XYZ and to enable completion for that, less so for
making it smart enough to complete "--some-prefix-opts="--foo=".

>> >> > I only had time to skim the patch, and I have to wonder why you pass
>> >> > around full-blown `rev_info` structs for range diff (and with that 
>> >> > really
>> >> > awful name `rd_rev`) rather than just the `diff_options` that you
>> >> > *actually* care about?
>> >>
>> >> Because setup_revisions() which does all the command-line parsing needs
>> >> a rev_info, so even if we only need the diffopt in the end we need to
>> >> initiate the whole thing.
>> >>
>> >> Suggestions for a better varibale name most welcome.
>> >
>> > `range_diff_revs`
>> >
>> > And you do not need to pass around the whole thing. You can easily pass
>> > `_diff_revs.diffopt`.
>> >
>> > Don't pass around what you do not need to pass around.
>>
>> Ah, you mean internally in log.c, yes that makes sense. I thought you
>> meant just pass diffopt to setup_revisions() (which needs the containing
>> struct). Willdo.
>
> Thanks,
> Dscho
>
>>
>> > Ciao,
>> > Dscho
>> >
>> >>
>> >> > Ciao,
>> >> > Dscho
>> >> >
>> >> >>
>> >> >> Ever since the "--range-diff" option was added in
>> >> >> 31e2617a5f ("format-patch: add --range-diff option to embed diff in
>> >> >> cover letter", 2018-07-22) the "rev->diffopt" we pass down to the diff
>> >> >> machinery has been the one we get from "format-patch"'s own
>> >> >> setup_revisions().
>> >> >>
>> >> >> This sort of thing is unique among the log-like commands in
>> >> >> builtin/log.c, no command than format-patch will embed the output of
>> >> >> another log-like command. Since the "rev->diffopt" is reused we need
>> >> >> to munge it before we pass it to show_range_diff(). See
>> >> >> 43dafc4172 ("format-patch: don't include --stat with --range-diff
>> >> 

Re: [PATCH] rebase: mark the C reimplementation as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)

2018-11-29 Thread Ian Jackson
Johannes Schindelin writes ("Re: [PATCH] rebase: mark the C reimplementation as 
an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)"):
> >  In a successful run with older git I get a reflog like this:
> > 
> >4833d74 HEAD@{0}: rebase finished: returning to 
> > refs/heads/with-preexisting
> >4833d74 HEAD@{1}: debrebase new-upstream 2.1-1: rebase: Add another new 
> > upstream file
> >cabd5ec HEAD@{2}: debrebase new-upstream 2.1-1: rebase: Edit the .c file
> >0b362ce HEAD@{3}: debrebase new-upstream 2.1-1: rebase: Add a new 
> > upstream file
> >29653e5 HEAD@{4}: debrebase new-upstream 2.1-1: rebase: checkout 
> > 29653e5a17bee4ac23a68bba3e12bc1f52858ac3
> >85e0c46 HEAD@{5}: debrebase: launder for new upstream
...
> >  This breaks the test because my test suite is checking that I set
> >  GIT_REFLOG_ACTION appropriately.
> > 
> >  If you want I can provide a minimal test case but this should suffice
> >  to see the bug I hope...
> 
> This should be plenty for me to get going. Thank you!

Happy hunting.

While you're looking at this, I observe that the fact that the `rebase
finished' message also does not honour GIT_REFLOG_ACTION appears to be
a pre-existing bug.

(In general one often can't rely on GIT_REFLOG_ACTION still being set
because the rebase might have been interrupted and restarted, which I
think is why my test case looks for it in the initial `checkout'
message.)

Regards,
Ian.

-- 
Ian JacksonThese opinions are my own.

If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
a private address which bypasses my fierce spamfilter.


Re: [PATCH v2 6/7] checkout: split into switch-branch and checkout-files

2018-11-29 Thread Duy Nguyen
On Thu, Nov 29, 2018 at 12:22 AM Stefan Xenos  wrote:
> Some behaviors I'd expect to see from these commands (I haven't yet
> checked to see if you've already done this):
>
> git checkout-files 
> should reset all the files in the repository regardless of the current
> directory - it should produce the same effect as "git reset --hard
>  && git reset HEAD@{1}". It should also delete
> locally-created files that aren't present in , such that the
> final working tree is exactly identical to what was committed in that
> tree-ish.
>
> git checkout-files foo -- myfile.txt
> should delete myfile.txt if it is present locally but not present in foo.
>
> git checkout-files foo -- .
> should recursively checkout all files in the current folder and all
> subfolders, and delete any locally-created files if they're not
> present in foo.

I think all these are the same as the non-overlay mode Thomas
mentioned [1]. Once he implements that in git-checkout, we can make it
default in checkout-files.

Two things though. I plan to get rid of "--" in checkout-files. The
main use case (I think) is reset from index, so you can just write

 git checkout-files somefiles

and if you want to get it from the tree(-ish) "foo", you do

 git checkout-files --from=foo somefiles

This form is easier to read (and even guess before you read man pages)
and leaves no room for ambiguation.

The second thing is, I plan to forbid "git checkout-files" without
arguments. If you want to reset the entire worktree, do

 git checkout-files :/

or just current dir

 git checkout-files .

Which brings us back to your "git checkout-files " use case
above. It should be treat the same way in my opinion, so we either do

 git checkout-files --from=tree-ish :/

or

 git checkout-files --from=tree-ish .

But "git checkout-files --from=tree-ish" alone is rejected.


[1] 
https://public-inbox.org/git/xmqqwoowo1fk@gitster-ct.c.googlers.com/T/#mdb076d178ccf0ae3dba0fd63143f99278047da93

> Suggestion:
> If git checkout-files overwrites or deletes any locally-modified files
> from the workspace or index, those files could be auto-stashed. That
> would make it easy to restore them in the event of a mistyped command.
> Auto-stashing could be suppressed with a command-line argument (with
> alternate behaviors being fail-if-modified or always-overwrite).

Stashing I think is not the right tool for this. When you stash, you
plan to retrieve it back later but here you should rarely ever need to
unstash until the accident. For recovery from accidents like this, I
have another thing in queue to achieve the same (I'm calling it
"backup log" now). So we will have the same functionality, just with
different means.

> Idea:
> If git checkout-files modifies the submodules file, it could also
> auto-update the submodules. (For example, with something like "git
> submodule update --init --recursive --progress").

This one is tricky because we should deal with submodule autoupdate
consistently across all porcelain commands (or at least common ones),
not just checkout-files. I'd prefer to delay this until later. Once we
figure out what to do with other commands, then we can still change
defaults for checkout-files.
-- 
Duy


Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Johannes Schindelin
Hi Ævar,

On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:

> On Thu, Nov 29 2018, Johannes Schindelin wrote:
> 
> > On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
> >
> >> On Thu, Nov 29 2018, Johannes Schindelin wrote:
> >>
> >> > On Wed, 28 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
> >> >
> >> >> Change the semantics of the "--range-diff" option so that the regular
> >> >> diff options can be provided separately for the range-diff and the
> >> >> patch. This allows for supplying e.g. --range-diff-U0 and -U1 to
> >> >> "format-patch" to provide different context for the range-diff and the
> >> >> patch. This wasn't possible before.
> >> >
> >> > I really, really dislike the `--range-diff-`. We have
> >> > precedent for passing optional arguments that are passed to some other
> >> > command, so a much more logical and consistent convention would be to use
> >> > `--range-diff[=..]`, allowing all of the diff options that
> >> > you might want to pass to the outer diff in one go rather than having a
> >> > lengthy string of `--range-diff-this` and `--range-diff-that` options.
> >>
> >> Where do we pass those sorts of arguments?
> >>
> >> Reasons I did it this way:
> >>
> >>  a) Passing it as one option will require the user to double-quote those
> >> options that take quoted arguments (e.g. --word-diff-regex), which I
> >> thought sucked more than the prefix. On the implementation side we
> >> couldn't leave the parsing of the command-line to the shell anymore.
> >>
> >>  b) I think people will want to tweak this very rarely, much more rarely
> >> than e.g. -U10 in format-patch itself, so having something long-ish
> >> doesn't sound bad.
> >
> > Hmm. I still don't like it. It sets a precedent, and we simply do not do
> > it that way in other circumstances (most obvious would be the -X merge
> > options). The more divergent user interfaces for the same sort of thing
> > are, the more brain cycles you force users to spend on navigating said
> > interfaces.
> 
> Yeah it sucks, I just think it sucks less than the alternative :)
> I.e. I'm not picky about --range-diff-* prefix the name, but I think
> doing our own shell parsing would be nasty.

What prevents you from using `sq_dequote_to_argv()`?

> >> > I only had time to skim the patch, and I have to wonder why you pass
> >> > around full-blown `rev_info` structs for range diff (and with that really
> >> > awful name `rd_rev`) rather than just the `diff_options` that you
> >> > *actually* care about?
> >>
> >> Because setup_revisions() which does all the command-line parsing needs
> >> a rev_info, so even if we only need the diffopt in the end we need to
> >> initiate the whole thing.
> >>
> >> Suggestions for a better varibale name most welcome.
> >
> > `range_diff_revs`
> >
> > And you do not need to pass around the whole thing. You can easily pass
> > `_diff_revs.diffopt`.
> >
> > Don't pass around what you do not need to pass around.
> 
> Ah, you mean internally in log.c, yes that makes sense. I thought you
> meant just pass diffopt to setup_revisions() (which needs the containing
> struct). Willdo.

Thanks,
Dscho

> 
> > Ciao,
> > Dscho
> >
> >>
> >> > Ciao,
> >> > Dscho
> >> >
> >> >>
> >> >> Ever since the "--range-diff" option was added in
> >> >> 31e2617a5f ("format-patch: add --range-diff option to embed diff in
> >> >> cover letter", 2018-07-22) the "rev->diffopt" we pass down to the diff
> >> >> machinery has been the one we get from "format-patch"'s own
> >> >> setup_revisions().
> >> >>
> >> >> This sort of thing is unique among the log-like commands in
> >> >> builtin/log.c, no command than format-patch will embed the output of
> >> >> another log-like command. Since the "rev->diffopt" is reused we need
> >> >> to munge it before we pass it to show_range_diff(). See
> >> >> 43dafc4172 ("format-patch: don't include --stat with --range-diff
> >> >> output", 2018-11-22) for a related regression fix which is being
> >> >> mostly reverted here.
> >> >>
> >> >> Implementation notes: 1) We're not bothering with the full teardown
> >> >> around die() and will leak memory, but it's too much boilerplate to do
> >> >> all the frees with/without the die() and not worth it. 2) We call
> >> >> repo_init_revisions() for "rd_rev" even though we could get away with
> >> >> a shallow copy like the code we're replacing (and which
> >> >> show_range_diff() itself does). This is to make this code more easily
> >> >> understood.
> >> >>
> >> >> Signed-off-by: Ævar Arnfjörð Bjarmason 
> >> >> ---
> >> >>  Documentation/git-format-patch.txt | 10 ++-
> >> >>  builtin/log.c  | 42 +++---
> >> >>  t/t3206-range-diff.sh  | 41 +
> >> >>  3 files changed, 82 insertions(+), 11 deletions(-)
> >> >>
> >> >> diff --git a/Documentation/git-format-patch.txt 
> >> >> b/Documentation/git-format-patch.txt
> >> >> index aba4c5febe..6c048f415f 100644
> >> >> --- 

Re: [PATCH] rebase: mark the C reimplementation as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)

2018-11-29 Thread Johannes Schindelin
Hi Ian,

On Thu, 29 Nov 2018, Ian Jackson wrote:

> Johannes Schindelin writes ("Re: [PATCH] rebase: mark the C reimplementation 
> as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)"):
> > if you could pry more information (or better information) out of that bug
> > reporter, that would be nice. Apparently my email address is blacklisted
> > by his mail provider, so he is unlikely to have received my previous mail
> > (nor will he receive this one, I am sure).
> 
> (I did receive this mail.  Sorry for the inconvenience, which sadly is
> inevitable occasionally in the modern email world.  FTR in future feel
> free to send the bounce to postmaster@chiark and I will make a
> you-shaped hole in my spamfilter.  Also with Debian bugs you can
> launder your messages by, eg, emailing 914695-submitter@bugs.)

Right. I myself have plenty of email-related problems that seem to crop up
this year in particular.

> > > > At https://bugs.debian.org/914695 is a report of a test regression in
> > > > an outside project that is very likely to have been triggered by the
> > > > new faster rebase code.
> 
> As I wrote in the bug report last night:
> 
>  https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914695#15
> 
>  I have investigated and the bug seems to be that git-rebase --onto now
>  fails to honour GIT_REFLOG_ACTION for the initial checkout.
> 
>  In a successful run with older git I get a reflog like this:
> 
>4833d74 HEAD@{0}: rebase finished: returning to refs/heads/with-preexisting
>4833d74 HEAD@{1}: debrebase new-upstream 2.1-1: rebase: Add another new 
> upstream file
>cabd5ec HEAD@{2}: debrebase new-upstream 2.1-1: rebase: Edit the .c file
>0b362ce HEAD@{3}: debrebase new-upstream 2.1-1: rebase: Add a new upstream 
> file
>29653e5 HEAD@{4}: debrebase new-upstream 2.1-1: rebase: checkout 
> 29653e5a17bee4ac23a68bba3e12bc1f52858ac3
>85e0c46 HEAD@{5}: debrebase: launder for new upstream
> 
>  With a newer git I get this:
> 
>6d3fb91 HEAD@{0}: rebase finished: returning to refs/heads/master
>6d3fb91 HEAD@{1}: debrebase new-upstream 2.1-1: rebase: Add another new 
> upstream file
>86c0721 HEAD@{2}: debrebase new-upstream 2.1-1: rebase: Edit the .c file
>50ba56c HEAD@{3}: debrebase new-upstream 2.1-1: rebase: Add a new upstream 
> file
>8272825 HEAD@{4}: rebase: checkout 8272825bb4ff6eba89afa936e32b6460f963a36a
>c78db55 HEAD@{5}: debrebase: launder for new upstream
> 
>  This breaks the test because my test suite is checking that I set
>  GIT_REFLOG_ACTION appropriately.
> 
>  If you want I can provide a minimal test case but this should suffice
>  to see the bug I hope...

This should be plenty for me to get going. Thank you!

Ciao,
Johannes

> 
> Regards
> Ian.
> 
> -- 
> Ian JacksonThese opinions are my own.
> 
> If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
> a private address which bypasses my fierce spamfilter.
> 


Re: Simple git push --tags deleted all branches

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Thu, Nov 29 2018, Mateusz Loskot wrote:

> On Thu, 29 Nov 2018 at 16:03, Ævar Arnfjörð Bjarmason  
> wrote:
>> On Wed, Nov 28 2018, Mateusz Loskot wrote:
>> >
>> > (using git version 2.19.2.windows.1)
>> >
>> > I've just encountered one of those WTH moments.
>> >
>> > I have a bare repository
>> >
>> > core.git (BARE:master) $ git branch
>> >   1.0
>> >   2.0
>> > * master
>> >
>> > core.git (BARE:master) $ git tag
>> > 1.0.1651
>> > 1.0.766
>> > 2.0.1103
>> > 2.0.1200
>> >
>> > I published the repo using: git push --all --follow-tags
>> >
>> > This succeeded, but there seem to be no tags pushed, just branches.
>> > So, I followed with
>> >
>> > core.git (BARE:master) $ git push --tags
>> > To XXX
>> >  - [deleted]   1.0
>> >  - [deleted]   2.0
>> >  ! [remote rejected]   master (refusing to delete the current
>> > branch: refs/heads/master)
>> > error: failed to push some refs to 'XXX'
>> >
>> > And, I've found out that all branches and tags have been
>> > wiped in both, local repo and remote :)
>> >
>> > I restored the repo and tried out
>> >
>> > git push origin 1.0
>> > git push origin --tags
>> >
>> > and this time both succeeded, without wiping out any refs.
>> >
>> > Could anyone help me to understand why remote-less
>> >
>> > git push --tags
>> >
>> > is/was so dangerous and unforgiving?!
>>
>> Since nobody's replied yet, I can't see what's going on here from the
>> info you've provided. My guess is that you have something "mirror" set
>> on the remote.
>
> Thank you for responding.
>
> The git push --tags hugely surprised me, and here is genuine screenshot
> https://twitter.com/mloskot/status/1068072285846859776
>
>> It seems you can't share the repo or its URL, but could you share the
>> scrubbed output of 'git config -l --show-origin' when run inside this
>> repository?
>
> Here is complete output. I have not stripped the basics like aliases,
> just in case.

Right, it's because you used --mirror, the important bit:

> file:config remote.origin.url=https://xxx.com/core-external-metadata.git
> file:config remote.origin.fetch=+refs/*:refs/*
> file:config remote.origin.mirror=true
> file:config

I.e. you have cloned with the --mirror flag, this is what it's supposed
to do: https://git-scm.com/docs/git-clone#git-clone---mirror
https://git-scm.com/docs/git-fetch#git-fetch---prune

I.e. you push and git tries to mirror the refs you have locally to the
remote, including pruning stuff in the remote.

This is useful, but not what you wanted here. It's used for e.g. making
an up-to-date copy of a repo from server A to server B in HA setups
where you'd like to fail over to server B and get the same refs you had
on A.


Re: [PATCH v1] mem_pool: add GIT_TRACE_MEMPOOL support

2018-11-29 Thread Johannes Schindelin
Hi Ben,

On Thu, 29 Nov 2018, Ben Peart wrote:

> On 11/28/2018 4:37 AM, Johannes Schindelin wrote:
> > Hi Ben,
> >
> > On Tue, 27 Nov 2018, Ben Peart wrote:
> >
> > > From: Ben Peart 
> > >
> > > Add tracing around initializing and discarding mempools. In discard report
> > > on the amount of memory unused in the current block to help tune setting
> > > the initial_size.
> > >
> > > Signed-off-by: Ben Peart 
> > > ---
> > Looks good.
> >
> > My only question: should we also trace calls to _alloc(), _calloc() and
> > _combine()?
> 
> I was trying to tune the initial size in my use of the mem_pool and so found
> this tracing useful to see how much memory was actually being used.  I'm
> inclined to only add tracing as it is needed rather that proactively because
> we think it _might_ be needed.  I suspect _alloc() and _calloc() would get
> very noisy and not add much value.

In other words, YAGNI. Makes sense.

Thanks,
Johannes

> 
> >
> > Ciao,
> > Johannes
> >
> > > Notes:
> > >  Base Ref: * git-trace-mempool
> > >  Web-Diff: https://github.com/benpeart/git/commit/9ac84bbca2
> > >  Checkout: git fetch https://github.com/benpeart/git
> > >  git-trace-mempool-v1 && git checkout 9ac84bbca2
> > >
> > >   mem-pool.c | 5 +
> > >   1 file changed, 5 insertions(+)
> > >
> > > diff --git a/mem-pool.c b/mem-pool.c
> > > index a2841a4a9a..065389aaec 100644
> > > --- a/mem-pool.c
> > > +++ b/mem-pool.c
> > > @@ -5,6 +5,7 @@
> > >   #include "cache.h"
> > >   #include "mem-pool.h"
> > >   
> > > +static struct trace_key trace_mem_pool = TRACE_KEY_INIT(MEMPOOL);
> > >   #define BLOCK_GROWTH_SIZE 1024*1024 - sizeof(struct mp_block);
> > >   
> > >   /*
> > > @@ -48,12 +49,16 @@ void mem_pool_init(struct mem_pool **mem_pool, size_t
> > > initial_size)
> > > mem_pool_alloc_block(pool, initial_size, NULL);
> > >   
> > >   *mem_pool = pool;
> > > + trace_printf_key(_mem_pool, "mem_pool (%p): init (%"PRIuMAX")
> > > initial size\n",
> > > + pool, (uintmax_t)initial_size);
> > >   }
> > >   
> > >   void mem_pool_discard(struct mem_pool *mem_pool, int invalidate_memory)
> > >   {
> > >struct mp_block *block, *block_to_free;
> > >   +   trace_printf_key(_mem_pool, "mem_pool (%p): discard 
> > > (%"PRIuMAX")
> > > unused\n",
> > > + mem_pool, (uintmax_t)(mem_pool->mp_block->end -
> > > mem_pool->mp_block->next_free));
> > >block = mem_pool->mp_block;
> > >while (block)
> > >{
> > >
> > > base-commit: bb75be6cb916297f271c846f2f9caa3daaaec718
> > > -- 
> > > 2.18.0.windows.1
> > >
> > >
> 
> 

Re: [PATCH v2 6/7] checkout: split into switch-branch and checkout-files

2018-11-29 Thread Duy Nguyen
On Thu, Nov 29, 2018 at 6:59 AM Junio C Hamano  wrote:
>
> Stefan Xenos  writes:
>
> > Although I have no problem with "switch-branch" as a command name,
> > some alternative names we might consider for switch-branch might be:
> >
> > chbranch
> > swbranch
>
> Please never go in that direction.  So far, we made a conscious
> effort to keep the names of most frequently used subcommand to
> proper words that can be understood by coders (IOW, I expect they
> know what 'grep' is, even though that may not be a 'proper word').
>
> > switch
> > branch change (as a subcommand for the "branch" command)
>
> It is more like moving to the branch to work on.  I think 'switch'
> is something SVN veterans may find familiar.  Both are much better
> than ch/swbranch that are overly cryptic.

OK I'll go with switch-branch and restore-files in the next round. And
perhaps consider just 'switch' and 'restore' later.
-- 
Duy


Re: [PATCH/RFC v2 0/7] Introduce new commands switch-branch and checkout-files

2018-11-29 Thread Duy Nguyen
On Wed, Nov 28, 2018 at 9:30 PM Stefan Beller  wrote:
>
> On Wed, Nov 28, 2018 at 12:09 PM Duy Nguyen  wrote:
> >
> > On Wed, Nov 28, 2018 at 9:01 PM Duy Nguyen  wrote:
> > > should we do
> > > something about detached HEAD in this switch-branch command (or
> > > whatever its name will be)?
> > >
> > > This is usually a confusing concept to new users
> >
> > And it just occurred to me that perhaps we should call this "unnamed
> > branch" (at least at high UI level) instead of detached HEAD. It is
> > technically not as accurate, but much better to understand.
>
> or 'direct' branch?

makes me think, what is an indirect branch?

> I mean 'detached HEAD' itself is also not correct
> as the HEAD points to a valid commit/tag usually, so it is attached to
> that content. The detachment comes from the implicit "from a branch".

Yeah I guess it's short for "HEAD that is detached from a branch"
-- 
Duy


Re: Simple git push --tags deleted all branches

2018-11-29 Thread Mateusz Loskot
On Thu, 29 Nov 2018 at 16:03, Ævar Arnfjörð Bjarmason  wrote:
> On Wed, Nov 28 2018, Mateusz Loskot wrote:
> >
> > (using git version 2.19.2.windows.1)
> >
> > I've just encountered one of those WTH moments.
> >
> > I have a bare repository
> >
> > core.git (BARE:master) $ git branch
> >   1.0
> >   2.0
> > * master
> >
> > core.git (BARE:master) $ git tag
> > 1.0.1651
> > 1.0.766
> > 2.0.1103
> > 2.0.1200
> >
> > I published the repo using: git push --all --follow-tags
> >
> > This succeeded, but there seem to be no tags pushed, just branches.
> > So, I followed with
> >
> > core.git (BARE:master) $ git push --tags
> > To XXX
> >  - [deleted]   1.0
> >  - [deleted]   2.0
> >  ! [remote rejected]   master (refusing to delete the current
> > branch: refs/heads/master)
> > error: failed to push some refs to 'XXX'
> >
> > And, I've found out that all branches and tags have been
> > wiped in both, local repo and remote :)
> >
> > I restored the repo and tried out
> >
> > git push origin 1.0
> > git push origin --tags
> >
> > and this time both succeeded, without wiping out any refs.
> >
> > Could anyone help me to understand why remote-less
> >
> > git push --tags
> >
> > is/was so dangerous and unforgiving?!
>
> Since nobody's replied yet, I can't see what's going on here from the
> info you've provided. My guess is that you have something "mirror" set
> on the remote.

Thank you for responding.

The git push --tags hugely surprised me, and here is genuine screenshot
https://twitter.com/mloskot/status/1068072285846859776

> It seems you can't share the repo or its URL, but could you share the
> scrubbed output of 'git config -l --show-origin' when run inside this
> repository?

Here is complete output. I have not stripped the basics like aliases,
just in case.

```
core-external-metadata.git (BARE:master) $ git config -l --show-origin
file:"C:\\ProgramData/Git/config"   core.symlinks=false
file:"C:\\ProgramData/Git/config"   core.autocrlf=true
file:"C:\\ProgramData/Git/config"   color.diff=auto
file:"C:\\ProgramData/Git/config"   color.status=auto
file:"C:\\ProgramData/Git/config"   color.branch=auto
file:"C:\\ProgramData/Git/config"   color.interactive=true
file:"C:\\ProgramData/Git/config"   help.format=html
file:"C:\\ProgramData/Git/config"   http.sslcainfo=C:/Program
Files/Git/mingw64/ssl/certs/ca-bundle.crt
file:"C:\\ProgramData/Git/config"   diff.astextplain.textconv=astextplain
file:"C:\\ProgramData/Git/config"   rebase.autosquash=true
file:C:/Program Files/Git/mingw64/etc/gitconfig
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
file:C:/Program Files/Git/mingw64/etc/gitconfig http.sslbackend=openssl
file:C:/Program Files/Git/mingw64/etc/gitconfig
diff.astextplain.textconv=astextplain
file:C:/Program Files/Git/mingw64/etc/gitconfig
filter.lfs.clean=git-lfs clean -- %f
file:C:/Program Files/Git/mingw64/etc/gitconfig
filter.lfs.smudge=git-lfs smudge -- %f
file:C:/Program Files/Git/mingw64/etc/gitconfig
filter.lfs.process=git-lfs filter-process
file:C:/Program Files/Git/mingw64/etc/gitconfig filter.lfs.required=true
file:C:/Program Files/Git/mingw64/etc/gitconfig credential.helper=manager
file:C:/Users/mateuszl/.gitconfig   user.name=Mateusz Łoskot
file:C:/Users/mateuszl/.gitconfig   user.email=mate...@loskot.net
file:C:/Users/mateuszl/.gitconfig   github.user=mloskot
file:C:/Users/mateuszl/.gitconfig   core.editor=vim
file:C:/Users/mateuszl/.gitconfig   color.branch=auto
file:C:/Users/mateuszl/.gitconfig   color.diff=auto
file:C:/Users/mateuszl/.gitconfig   color.status=auto
file:C:/Users/mateuszl/.gitconfig   color.ui=auto
file:C:/Users/mateuszl/.gitconfig   alias.br=branch
file:C:/Users/mateuszl/.gitconfig   alias.bv=branch -vv
file:C:/Users/mateuszl/.gitconfig   alias.brv=branch -vv
file:C:/Users/mateuszl/.gitconfig   alias.bra=branch -a
file:C:/Users/mateuszl/.gitconfig   alias.ci=commit --verbose
file:C:/Users/mateuszl/.gitconfig   alias.cia=commit --verbose --amend
file:C:/Users/mateuszl/.gitconfig   alias.ciae=commit --verbose
--amend --no-edit
file:C:/Users/mateuszl/.gitconfig   alias.co=checkout
file:C:/Users/mateuszl/.gitconfig   alias.dc=diff --cached
file:C:/Users/mateuszl/.gitconfig   alias.df=diff
file:C:/Users/mateuszl/.gitconfig   alias.gf=flow
file:C:/Users/mateuszl/.gitconfig   alias.lg=log --color --graph
--pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)
%C(bold blue)<%an>%Creset' --abbrev-commit
file:C:/Users/mateuszl/.gitconfig   alias.lol=log --graph
--decorate --pretty=oneline --abbrev-commit
file:C:/Users/mateuszl/.gitconfig   alias.lola=log --graph
--decorate --pretty=oneline --abbrev-commit --all
file:C:/Users/mateuszl/.gitconfig   alias.ls=ls-files
file:C:/Users/mateuszl/.gitconfig   alias.lst=lfs status
file:C:/Users/mateuszl/.gitconfig   alias.rt=remote

Re: Git Tags

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Thu, Nov 29 2018, Stefanie Leisestreichler wrote:

> Hi.
>
> I have done this (on box A):
>
> git commit -m "Message"
> git tag -a 0.9.0
> git push origin master
>
> In my local repository, when I run "git tag" it is showing me "0.9.0".
>
> Then I did (on box B)
> git clone ssh://user@host:/path/project.git
> cd project
> git tag
>
> Now git tag is showing nothing.
>
> Why is the tag only available in my local repository?
>
> Also when I try to
> git clone --branch 0.9.0 ssh://user@host:/path/project.git
> it tells me: fatal:remote branch not found in upstream repository origin

Because --branch  means get refs/heads/, tags are not
branches. However, because we're apparently quite loose about this in
the clone/fetch code this does give you the tag if it exists, but
probably not in the way you expect.

We interpret the argument as a branch, and will get not only this tag
but "follow" (see --no-tags in git-fetch(1)) the tag as though it were a
branch and give you all tags leading up to that one. This would give you
a single tag:

git clone --no-tags --branch v2.19.0 --single-branch 
https://github.com/git/git.git

But this is a more direct way to do it:

git init git; git -C git fetch --no-tags https://github.com/git/git.git tag 
v2.19.0

Which'll since you said it failed that's because you haven't pushed the
tag. Try 'git ls-remote ' to see if it's there (it's not).


Re: Simple git push --tags deleted all branches

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Wed, Nov 28 2018, Mateusz Loskot wrote:

> Hi,
>
> (using git version 2.19.2.windows.1)
>
> I've just encountered one of those WTH moments.
>
> I have a bare repository
>
> core.git (BARE:master) $ git branch
>   1.0
>   2.0
> * master
>
> core.git (BARE:master) $ git tag
> 1.0.1651
> 1.0.766
> 2.0.1103
> 2.0.1200
>
> I published the repo using: git push --all --follow-tags
>
> This succeeded, but there seem to be no tags pushed, just branches.
> So, I followed with
>
> core.git (BARE:master) $ git push --tags
> To XXX
>  - [deleted]   1.0
>  - [deleted]   2.0
>  ! [remote rejected]   master (refusing to delete the current
> branch: refs/heads/master)
> error: failed to push some refs to 'XXX'
>
> And, I've found out that all branches and tags have been
> wiped in both, local repo and remote :)
>
> I restored the repo and tried out
>
> git push origin 1.0
> git push origin --tags
>
> and this time both succeeded, without wiping out any refs.
>
> Could anyone help me to understand why remote-less
>
> git push --tags
>
> is/was so dangerous and unforgiving?!

Since nobody's replied yet, I can't see what's going on here from the
info you've provided. My guess is that you have something "mirror" set
on the remote.

It seems you can't share the repo or its URL, but could you share the
scrubbed output of 'git config -l --show-origin' when run inside this
repository?


Re: [PATCH] rebase: mark the C reimplementation as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)

2018-11-29 Thread Ian Jackson
Johannes Schindelin writes ("Re: [PATCH] rebase: mark the C reimplementation as 
an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)"):
> if you could pry more information (or better information) out of that bug
> reporter, that would be nice. Apparently my email address is blacklisted
> by his mail provider, so he is unlikely to have received my previous mail
> (nor will he receive this one, I am sure).

(I did receive this mail.  Sorry for the inconvenience, which sadly is
inevitable occasionally in the modern email world.  FTR in future feel
free to send the bounce to postmaster@chiark and I will make a
you-shaped hole in my spamfilter.  Also with Debian bugs you can
launder your messages by, eg, emailing 914695-submitter@bugs.)

> > > At https://bugs.debian.org/914695 is a report of a test regression in
> > > an outside project that is very likely to have been triggered by the
> > > new faster rebase code.

As I wrote in the bug report last night:

 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914695#15

 I have investigated and the bug seems to be that git-rebase --onto now
 fails to honour GIT_REFLOG_ACTION for the initial checkout.

 In a successful run with older git I get a reflog like this:

   4833d74 HEAD@{0}: rebase finished: returning to refs/heads/with-preexisting
   4833d74 HEAD@{1}: debrebase new-upstream 2.1-1: rebase: Add another new 
upstream file
   cabd5ec HEAD@{2}: debrebase new-upstream 2.1-1: rebase: Edit the .c file
   0b362ce HEAD@{3}: debrebase new-upstream 2.1-1: rebase: Add a new upstream 
file
   29653e5 HEAD@{4}: debrebase new-upstream 2.1-1: rebase: checkout 
29653e5a17bee4ac23a68bba3e12bc1f52858ac3
   85e0c46 HEAD@{5}: debrebase: launder for new upstream

 With a newer git I get this:

   6d3fb91 HEAD@{0}: rebase finished: returning to refs/heads/master
   6d3fb91 HEAD@{1}: debrebase new-upstream 2.1-1: rebase: Add another new 
upstream file
   86c0721 HEAD@{2}: debrebase new-upstream 2.1-1: rebase: Edit the .c file
   50ba56c HEAD@{3}: debrebase new-upstream 2.1-1: rebase: Add a new upstream 
file
   8272825 HEAD@{4}: rebase: checkout 8272825bb4ff6eba89afa936e32b6460f963a36a
   c78db55 HEAD@{5}: debrebase: launder for new upstream

 This breaks the test because my test suite is checking that I set
 GIT_REFLOG_ACTION appropriately.

 If you want I can provide a minimal test case but this should suffice
 to see the bug I hope...

Regards
Ian.

-- 
Ian JacksonThese opinions are my own.

If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
a private address which bypasses my fierce spamfilter.


[PATCH v2 5/6] pack-objects: create pack.useSparse setting

2018-11-29 Thread Derrick Stolee via GitGitGadget
From: Derrick Stolee 

The '--sparse' flag in 'git pack-objects' changes the algorithm
used to enumerate objects to one that is faster for individual
users pushing new objects that change only a small cone of the
working directory. The sparse algorithm is not recommended for a
server, which likely sends new objects that appear across the
entire working directory.

Create a 'pack.useSparse' setting that enables this new algorithm.
This allows 'git push' to use this algorithm without passing a
'--sparse' flag all the way through four levels of run_command()
calls.

If the '--no-sparse' flag is set, then this config setting is
overridden.

Signed-off-by: Derrick Stolee 
---
 builtin/pack-objects.c |  4 
 t/t5322-pack-objects-sparse.sh | 15 +++
 2 files changed, 19 insertions(+)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 7d5b0735e3..124b1bafc4 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2711,6 +2711,10 @@ static int git_pack_config(const char *k, const char *v, 
void *cb)
use_bitmap_index_default = git_config_bool(k, v);
return 0;
}
+   if (!strcmp(k, "pack.usesparse")) {
+   sparse = git_config_bool(k, v);
+   return 0;
+   }
if (!strcmp(k, "pack.threads")) {
delta_search_threads = git_config_int(k, v);
if (delta_search_threads < 0)
diff --git a/t/t5322-pack-objects-sparse.sh b/t/t5322-pack-objects-sparse.sh
index 45dba6e014..8f5699bd91 100755
--- a/t/t5322-pack-objects-sparse.sh
+++ b/t/t5322-pack-objects-sparse.sh
@@ -121,4 +121,19 @@ test_expect_success 'sparse pack-objects' '
test_cmp expect_sparse_objects.txt sparse_objects.txt
 '
 
+test_expect_success 'pack.useSparse enables algorithm' '
+   git config pack.useSparse true &&
+   git pack-objects --stdout --revs sparse.pack &&
+   git index-pack -o sparse.idx sparse.pack &&
+   git show-index sparse_objects.txt &&
+   test_cmp expect_sparse_objects.txt sparse_objects.txt
+'
+
+test_expect_success 'pack.useSparse overridden' '
+   git pack-objects --stdout --revs --no-sparse sparse.pack &&
+   git index-pack -o sparse.idx sparse.pack &&
+   git show-index sparse_objects.txt &&
+   test_cmp expect_objects.txt sparse_objects.txt
+'
+
 test_done
-- 
gitgitgadget



[PATCH v2 0/6] Add a new "sparse" tree walk algorithm

2018-11-29 Thread Derrick Stolee via GitGitGadget
One of the biggest remaining pain points for users of very large
repositories is the time it takes to run 'git push'. We inspected some slow
pushes by our developers and found that the "Enumerating Objects" phase of a
push was very slow. This is unsurprising, because this is why reachability
bitmaps exist. However, reachability bitmaps are not available to us because
of the single pack-file requirement. The bitmap approach is intended for
servers anyway, and clients have a much different behavior pattern.

Specifically, clients are normally pushing a very small number of objects
compared to the entire working directory. A typical user changes only a
small cone of the working directory, so let's use that to our benefit.

Create a new "sparse" mode for 'git pack-objects' that uses the paths that
introduce new objects to direct our search into the reachable trees. By
collecting trees at each path, we can then recurse into a path only when
there are uninteresting and interesting trees at that path. This gains a
significant performance boost for small topics while presenting a
possibility of packing extra objects.

The main algorithm change is in patch 4, but is set up a little bit in
patches 1 and 2.

As demonstrated in the included test script, we see that the existing
algorithm can send extra objects due to the way we specify the "frontier".
But we can send even more objects if a user copies objects from one folder
to another. I say "copy" because a rename would (usually) change the
original folder and trigger a walk into that path, discovering the objects.

In order to benefit from this approach, the user can opt-in using the
pack.useSparse config setting. This setting can be overridden using the
'--no-sparse' option.

Update in V2: 

 * Added GIT_TEST_PACK_SPARSE test option.
 * Fixed test breakages when GIT_TEST_PACK_SPARSE is enabled by adding null
   checks.

Derrick Stolee (6):
  revision: add mark_tree_uninteresting_sparse
  list-objects: consume sparse tree walk
  pack-objects: add --sparse option
  revision: implement sparse algorithm
  pack-objects: create pack.useSparse setting
  pack-objects: create GIT_TEST_PACK_SPARSE

 Documentation/git-pack-objects.txt |   9 +-
 bisect.c   |   2 +-
 builtin/pack-objects.c |  10 ++-
 builtin/rev-list.c |   2 +-
 http-push.c|   2 +-
 list-objects.c |  55 +++-
 list-objects.h |   4 +-
 revision.c | 121 +
 revision.h |   2 +
 t/README   |   4 +
 t/t5322-pack-objects-sparse.sh | 139 +
 11 files changed, 340 insertions(+), 10 deletions(-)
 create mode 100755 t/t5322-pack-objects-sparse.sh


base-commit: a1598010f775d82b5adf12c29d0f5bc9b41434c6
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-89%2Fderrickstolee%2Fpush%2Fsparse-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-89/derrickstolee/push/sparse-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/89

Range-diff vs v1:

 1:  b73b8de98c = 1:  60617681f7 revision: add mark_tree_uninteresting_sparse
 2:  9bf04c748b ! 2:  4527addacb list-objects: consume sparse tree walk
 @@ -116,6 +116,10 @@
  + for (parents = commit->parents; parents; parents = parents->next) {
  + struct commit *parent = parents->item;
  + struct tree *tree = get_commit_tree(parent);
 ++
 ++ if (!tree)
 ++ continue;
 ++
  + oidset_insert(set, >object.oid);
  +
  + if (!(parent->object.flags & UNINTERESTING))
 @@ -142,14 +146,14 @@
  +
for (list = revs->commits; list; list = list->next) {
struct commit *commit = list->item;
 -+ 
 + 
 +- if (commit->object.flags & UNINTERESTING) {
  + if (sparse) {
  + struct tree *tree = get_commit_tree(commit);
 -+ 
 ++
  + if (commit->object.flags & UNINTERESTING)
  + tree->object.flags |= UNINTERESTING;
 - 
 -- if (commit->object.flags & UNINTERESTING) {
 ++
  + oidset_insert(, >object.oid);
  + add_edge_parents(commit, revs, show_edge, );
  + } else if (commit->object.flags & UNINTERESTING) {
 @@ -189,3 +193,17 @@
   
   struct oidset;
   struct list_objects_filter_options;
 +
 +diff --git a/revision.c b/revision.c
 +--- a/revision.c
  b/revision.c
 +@@
 +  while ((oid = oidset_iter_next())) {
 +  struct tree *tree = lookup_tree(r, oid);
 + 
 ++ if (!tree)
 ++ continue;
 ++
 +  if (tree->object.flags & UNINTERESTING) {
 +  /*
 +   * Remove 

[PATCH v2 1/6] revision: add mark_tree_uninteresting_sparse

2018-11-29 Thread Derrick Stolee via GitGitGadget
From: Derrick Stolee 

In preparation for a new algorithm that walks fewer trees when
creating a pack from a set of revisions, create a method that
takes an oidset of tree oids and marks reachable objects as
UNINTERESTING.

The current implementation uses the existing
mark_tree_uninteresting to recursively walk the trees and blobs.
This will walk the same number of trees as the old mechanism.

There is one new assumption in this approach: we are also given
the oids of the interesting trees. This implementation does not
use those trees at the moment, but we will use them in a later
rewrite of this method.

Signed-off-by: Derrick Stolee 
---
 revision.c | 22 ++
 revision.h |  2 ++
 2 files changed, 24 insertions(+)

diff --git a/revision.c b/revision.c
index 13e0519c02..3a62c7c187 100644
--- a/revision.c
+++ b/revision.c
@@ -99,6 +99,28 @@ void mark_tree_uninteresting(struct repository *r, struct 
tree *tree)
mark_tree_contents_uninteresting(r, tree);
 }
 
+void mark_trees_uninteresting_sparse(struct repository *r,
+struct oidset *set)
+{
+   struct object_id *oid;
+   struct oidset_iter iter;
+
+   oidset_iter_init(set, );
+   while ((oid = oidset_iter_next())) {
+   struct tree *tree = lookup_tree(r, oid);
+
+   if (tree->object.flags & UNINTERESTING) {
+   /*
+* Remove the flag so the next call
+* is not a no-op. The flag is added
+* in mark_tree_unintersting().
+*/
+   tree->object.flags ^= UNINTERESTING;
+   mark_tree_uninteresting(r, tree);
+   }
+   }
+}
+
 struct commit_stack {
struct commit **items;
size_t nr, alloc;
diff --git a/revision.h b/revision.h
index 7987bfcd2e..f828e91ae9 100644
--- a/revision.h
+++ b/revision.h
@@ -67,6 +67,7 @@ struct rev_cmdline_info {
 #define REVISION_WALK_NO_WALK_SORTED 1
 #define REVISION_WALK_NO_WALK_UNSORTED 2
 
+struct oidset;
 struct topo_walk_info;
 
 struct rev_info {
@@ -327,6 +328,7 @@ void put_revision_mark(const struct rev_info *revs,
 
 void mark_parents_uninteresting(struct commit *commit);
 void mark_tree_uninteresting(struct repository *r, struct tree *tree);
+void mark_trees_uninteresting_sparse(struct repository *r, struct oidset *set);
 
 void show_object_with_name(FILE *, struct object *, const char *);
 
-- 
gitgitgadget



[PATCH v2 2/6] list-objects: consume sparse tree walk

2018-11-29 Thread Derrick Stolee via GitGitGadget
From: Derrick Stolee 

When creating a pack-file using 'git pack-objects --revs' we provide
a list of interesting and uninteresting commits. For example, a push
operation would make the local topic branch be interesting and the
known remote refs as uninteresting. We want to discover the set of
new objects to send to the server as a thin pack.

We walk these commits until we discover a frontier of commits such
that every commit walk starting at interesting commits ends in a root
commit or unintersting commit. We then need to discover which
non-commit objects are reachable from  uninteresting commits.

The mark_edges_unintersting() method in list-objects.c iterates on
the commit list and does the following:

* If the commit is UNINTERSTING, then mark its root tree and every
  object it can reach as UNINTERESTING.

* If the commit is interesting, then mark the root tree of every
  UNINTERSTING parent (and all objects that tree can reach) as
  UNINTERSTING.

At the very end, we repeat the process on every commit directly
given to the revision walk from stdin. This helps ensure we properly
cover shallow commits that otherwise were not included in the
frontier.

The logic to recursively follow trees is in the
mark_tree_uninteresting() method in revision.c. The algorithm avoids
duplicate work by not recursing into trees that are already marked
UNINTERSTING.

Add a new 'sparse' option to the mark_edges_uninteresting() method
that performs this logic in a slightly new way. As we iterate over
the commits, we add all of the root trees to an oidset. Then, call
mark_trees_uninteresting_sparse() on that oidset. Note that we
include interesting trees in this process. The current implementation
of mark_trees_unintersting_sparse() will walk the same trees as
the old logic, but this will be replaced in a later change.

The sparse option is not used by any callers at the moment, but
will be wired to 'git pack-objects' in the next change.

Signed-off-by: Derrick Stolee 
---
 bisect.c   |  2 +-
 builtin/pack-objects.c |  2 +-
 builtin/rev-list.c |  2 +-
 http-push.c|  2 +-
 list-objects.c | 55 +++---
 list-objects.h |  4 ++-
 revision.c |  3 +++
 7 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/bisect.c b/bisect.c
index 487675c672..842f8b4b8f 100644
--- a/bisect.c
+++ b/bisect.c
@@ -656,7 +656,7 @@ static void bisect_common(struct rev_info *revs)
if (prepare_revision_walk(revs))
die("revision walk setup failed");
if (revs->tree_objects)
-   mark_edges_uninteresting(revs, NULL);
+   mark_edges_uninteresting(revs, NULL, 0);
 }
 
 static void exit_if_skipped_commits(struct commit_list *tried,
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 411aefd687..5f70d840a7 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3135,7 +3135,7 @@ static void get_object_list(int ac, const char **av)
 
if (prepare_revision_walk())
die(_("revision walk setup failed"));
-   mark_edges_uninteresting(, show_edge);
+   mark_edges_uninteresting(, show_edge, 0);
 
if (!fn_show_object)
fn_show_object = show_object;
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 2880ed37e3..9663cbfae0 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -543,7 +543,7 @@ int cmd_rev_list(int argc, const char **argv, const char 
*prefix)
if (prepare_revision_walk())
die("revision walk setup failed");
if (revs.tree_objects)
-   mark_edges_uninteresting(, show_edge);
+   mark_edges_uninteresting(, show_edge, 0);
 
if (bisect_list) {
int reaches, all;
diff --git a/http-push.c b/http-push.c
index cd48590912..ea52d6f9f6 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1933,7 +1933,7 @@ int cmd_main(int argc, const char **argv)
pushing = 0;
if (prepare_revision_walk())
die("revision walk setup failed");
-   mark_edges_uninteresting(, NULL);
+   mark_edges_uninteresting(, NULL, 0);
objects_to_send = get_delta(, ref_lock);
finish_all_active_slots();
 
diff --git a/list-objects.c b/list-objects.c
index c41cc80db5..4fbdeca0a4 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -222,25 +222,72 @@ static void mark_edge_parents_uninteresting(struct commit 
*commit,
}
 }
 
-void mark_edges_uninteresting(struct rev_info *revs, show_edge_fn show_edge)
+static void add_edge_parents(struct commit *commit,
+struct rev_info *revs,
+show_edge_fn show_edge,
+struct oidset *set)
+{
+   struct commit_list *parents;
+
+   for (parents = commit->parents; parents; parents = parents->next) {
+   struct commit *parent = parents->item;
+  

Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Thu, Nov 29 2018, Johannes Schindelin wrote:

> Hi Ævar,
>
> On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
>
>> On Thu, Nov 29 2018, Johannes Schindelin wrote:
>>
>> > On Wed, 28 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
>> >
>> >> Change the semantics of the "--range-diff" option so that the regular
>> >> diff options can be provided separately for the range-diff and the
>> >> patch. This allows for supplying e.g. --range-diff-U0 and -U1 to
>> >> "format-patch" to provide different context for the range-diff and the
>> >> patch. This wasn't possible before.
>> >
>> > I really, really dislike the `--range-diff-`. We have
>> > precedent for passing optional arguments that are passed to some other
>> > command, so a much more logical and consistent convention would be to use
>> > `--range-diff[=..]`, allowing all of the diff options that
>> > you might want to pass to the outer diff in one go rather than having a
>> > lengthy string of `--range-diff-this` and `--range-diff-that` options.
>>
>> Where do we pass those sorts of arguments?
>>
>> Reasons I did it this way:
>>
>>  a) Passing it as one option will require the user to double-quote those
>> options that take quoted arguments (e.g. --word-diff-regex), which I
>> thought sucked more than the prefix. On the implementation side we
>> couldn't leave the parsing of the command-line to the shell anymore.
>>
>>  b) I think people will want to tweak this very rarely, much more rarely
>> than e.g. -U10 in format-patch itself, so having something long-ish
>> doesn't sound bad.
>
> Hmm. I still don't like it. It sets a precedent, and we simply do not do
> it that way in other circumstances (most obvious would be the -X merge
> options). The more divergent user interfaces for the same sort of thing
> are, the more brain cycles you force users to spend on navigating said
> interfaces.

Yeah it sucks, I just think it sucks less than the alternative :)
I.e. I'm not picky about --range-diff-* prefix the name, but I think
doing our own shell parsing would be nasty.

>> > I only had time to skim the patch, and I have to wonder why you pass
>> > around full-blown `rev_info` structs for range diff (and with that really
>> > awful name `rd_rev`) rather than just the `diff_options` that you
>> > *actually* care about?
>>
>> Because setup_revisions() which does all the command-line parsing needs
>> a rev_info, so even if we only need the diffopt in the end we need to
>> initiate the whole thing.
>>
>> Suggestions for a better varibale name most welcome.
>
> `range_diff_revs`
>
> And you do not need to pass around the whole thing. You can easily pass
> `_diff_revs.diffopt`.
>
> Don't pass around what you do not need to pass around.

Ah, you mean internally in log.c, yes that makes sense. I thought you
meant just pass diffopt to setup_revisions() (which needs the containing
struct). Willdo.

> Ciao,
> Dscho
>
>>
>> > Ciao,
>> > Dscho
>> >
>> >>
>> >> Ever since the "--range-diff" option was added in
>> >> 31e2617a5f ("format-patch: add --range-diff option to embed diff in
>> >> cover letter", 2018-07-22) the "rev->diffopt" we pass down to the diff
>> >> machinery has been the one we get from "format-patch"'s own
>> >> setup_revisions().
>> >>
>> >> This sort of thing is unique among the log-like commands in
>> >> builtin/log.c, no command than format-patch will embed the output of
>> >> another log-like command. Since the "rev->diffopt" is reused we need
>> >> to munge it before we pass it to show_range_diff(). See
>> >> 43dafc4172 ("format-patch: don't include --stat with --range-diff
>> >> output", 2018-11-22) for a related regression fix which is being
>> >> mostly reverted here.
>> >>
>> >> Implementation notes: 1) We're not bothering with the full teardown
>> >> around die() and will leak memory, but it's too much boilerplate to do
>> >> all the frees with/without the die() and not worth it. 2) We call
>> >> repo_init_revisions() for "rd_rev" even though we could get away with
>> >> a shallow copy like the code we're replacing (and which
>> >> show_range_diff() itself does). This is to make this code more easily
>> >> understood.
>> >>
>> >> Signed-off-by: Ævar Arnfjörð Bjarmason 
>> >> ---
>> >>  Documentation/git-format-patch.txt | 10 ++-
>> >>  builtin/log.c  | 42 +++---
>> >>  t/t3206-range-diff.sh  | 41 +
>> >>  3 files changed, 82 insertions(+), 11 deletions(-)
>> >>
>> >> diff --git a/Documentation/git-format-patch.txt 
>> >> b/Documentation/git-format-patch.txt
>> >> index aba4c5febe..6c048f415f 100644
>> >> --- a/Documentation/git-format-patch.txt
>> >> +++ b/Documentation/git-format-patch.txt
>> >> @@ -24,7 +24,8 @@ SYNOPSIS
>> >>  [--to=] [--cc=]
>> >>  [--[no-]cover-letter] [--quiet] [--notes[=]]
>> >>  [--interdiff=]
>> >> -[--range-diff= [--creation-factor=]]
>> >> +[--range-diff= 

[PATCH v2 6/6] pack-objects: create GIT_TEST_PACK_SPARSE

2018-11-29 Thread Derrick Stolee via GitGitGadget
From: Derrick Stolee 

Create a test variable GIT_TEST_PACK_SPARSE to enable the sparse
object walk algorithm by default during the test suite. Enabling
this variable ensures coverage in many interesting cases, such as
shallow clones, partial clones, and missing objects.

Signed-off-by: Derrick Stolee 
---
 builtin/pack-objects.c | 1 +
 t/README   | 4 
 t/t5322-pack-objects-sparse.sh | 6 +++---
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 124b1bafc4..507d381153 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3331,6 +3331,7 @@ int cmd_pack_objects(int argc, const char **argv, const 
char *prefix)
 
read_replace_refs = 0;
 
+   sparse = git_env_bool("GIT_TEST_PACK_SPARSE", 0);
reset_pack_idx_option(_idx_opts);
git_config(git_pack_config, NULL);
 
diff --git a/t/README b/t/README
index 28711cc508..8b6dfe1864 100644
--- a/t/README
+++ b/t/README
@@ -342,6 +342,10 @@ GIT_TEST_INDEX_VERSION= exercises the index read/write 
code path
 for the index version specified.  Can be set to any valid version
 (currently 2, 3, or 4).
 
+GIT_TEST_PACK_SPARSE= if enabled will default the pack-objects
+builtin to use the sparse object walk. This can still be overridden by
+the --no-sparse command-line argument.
+
 GIT_TEST_PRELOAD_INDEX= exercises the preload-index code path
 by overriding the minimum number of cache entries required per thread.
 
diff --git a/t/t5322-pack-objects-sparse.sh b/t/t5322-pack-objects-sparse.sh
index 8f5699bd91..e8cf41d1c6 100755
--- a/t/t5322-pack-objects-sparse.sh
+++ b/t/t5322-pack-objects-sparse.sh
@@ -36,7 +36,7 @@ test_expect_success 'setup repo' '
 '
 
 test_expect_success 'non-sparse pack-objects' '
-   git pack-objects --stdout --revs nonsparse.pack &&
+   git pack-objects --stdout --revs --no-sparse nonsparse.pack &&
git index-pack -o nonsparse.idx nonsparse.pack &&
git show-index nonsparse_objects.txt &&
test_cmp expect_objects.txt nonsparse_objects.txt
@@ -70,7 +70,7 @@ test_expect_success 'duplicate a folder from f3 and commit to 
topic1' '
 '
 
 test_expect_success 'non-sparse pack-objects' '
-   git pack-objects --stdout --revs nonsparse.pack &&
+   git pack-objects --stdout --revs --no-sparse nonsparse.pack &&
git index-pack -o nonsparse.idx nonsparse.pack &&
git show-index nonsparse_objects.txt &&
test_cmp expect_objects.txt nonsparse_objects.txt
@@ -102,7 +102,7 @@ test_expect_success 'non-sparse pack-objects' '
topic1  \
topic1^{tree}   \
topic1:f3 | sort >expect_objects.txt &&
-   git pack-objects --stdout --revs nonsparse.pack &&
+   git pack-objects --stdout --revs --no-sparse nonsparse.pack &&
git index-pack -o nonsparse.idx nonsparse.pack &&
git show-index nonsparse_objects.txt &&
test_cmp expect_objects.txt nonsparse_objects.txt
-- 
gitgitgadget


[PATCH v2 4/6] revision: implement sparse algorithm

2018-11-29 Thread Derrick Stolee via GitGitGadget
From: Derrick Stolee 

When enumerating objects to place in a pack-file during 'git
pack-objects --revs', we discover the "frontier" of commits
that we care about and the boundary with commit we find
uninteresting. From that point, we walk trees to discover which
trees and blobs are uninteresting. Finally, we walk trees to find
the interesting trees.

This commit introduces a new, "sparse" way to discover the
uninteresting trees. We use the perspective of a single user trying
to push their topic to a large repository. That user likely changed
a very small fraction of the paths in their working directory, but
we spend a lot of time walking all reachable trees.

The way to switch the logic to work in this sparse way is to start
caring about which paths introduce new trees. While it is not
possible to generate a diff between the frontier boundary and all
of the interesting commits, we can simulate that behavior by
inspecting all of the root trees as a whole, then recursing down
to the set of trees at each path.

We already had taken the first step by passing an oidset to
mark_trees_uninteresting_sparse(). We now create a dictionary
whose keys are paths and values are oidsets. We consider the set
of trees that appear at each path. While we inspect a tree, we
add its subtrees to the oidsets corresponding to the tree entry's
path. We also mark trees as UNINTERESTING if the tree we are
parsing is UNINTERESTING.

To actually improve the peformance, we need to terminate our
recursion unless the oidset contains some intersting trees and
some uninteresting trees. Technically, we only need one interesting
tree for this to speed up in most cases, but we also will not mark
anything UNINTERESTING if there are no uninteresting trees, so
that would be wasted effort.

There are a few ways that this is not a universally better option.

First, we can pack extra objects. If someone copies a subtree
from one tree to another, the first tree will appear UNINTERESTING
and we will not recurse to see that the subtree should also be
UNINTERESTING. We will walk the new tree and see the subtree as
a "new" object and add it to the pack. We add a test case that
demonstrates this as a way to prove that the --sparse option is
actually working.

Second, we can have extra memory pressure. If instead of being a
single user pushing a small topic we are a server sending new
objects from across the entire working directory, then we will
gain very little (the recursion will rarely terminate early) but
will spend extra time maintaining the path-oidset dictionaries.

Despite these potential drawbacks, the benefits of the algorithm
are clear. By adding a counter to 'add_children_by_path' and
'mark_tree_contents_uninteresting', I measured the number of
parsed trees for the two algorithms in a variety of repos.

For git.git, I used the following input:

v2.19.0
^v2.19.0~10

 Objects to pack: 550
Walked (old alg): 282
Walked (new alg): 130

For the Linux repo, I used the following input:

v4.18
^v4.18~10

 Objects to pack:   518
Walked (old alg): 4,836
Walked (new alg):   188

The two repos above are rather "wide and flat" compared to
other repos that I have used in the past. As a comparison,
I tested an old topic branch in the Azure DevOps repo, which
has a much deeper folder structure than the Linux repo.

 Objects to pack:220
Walked (old alg): 22,804
Walked (new alg):129

I used the number of walked trees the main metric above because
it is consistent across multiple runs. When I ran my tests, the
performance of the pack-objects command with the same options
could change the end-to-end time by 10x depending on the file
system being warm. However, by repeating the same test on repeat
I could get more consistent timing results. The git.git and
Linux tests were too fast overall (less than 0.5s) to measure
an end-to-end difference. The Azure DevOps case was slow enough
to see the time improve from 15s to 1s in the warm case. The
cold case was 90s to 9s in my testing.

These improvements will have even larger benefits in the super-
large Windows repository. In our experiments, we see the
"Enumerate objects" phase of pack-objects taking 60-80% of the
end-to-end time of non-trivial pushes, taking longer than the
network time to send the pack and the server time to verify the
pack.

Signed-off-by: Derrick Stolee 
---
 revision.c | 116 ++---
 t/t5322-pack-objects-sparse.sh |  21 --
 2 files changed, 121 insertions(+), 16 deletions(-)

diff --git a/revision.c b/revision.c
index f9eb6400f1..971f1bb095 100644
--- a/revision.c
+++ b/revision.c
@@ -99,29 +99,125 @@ void mark_tree_uninteresting(struct repository *r, struct 
tree *tree)
mark_tree_contents_uninteresting(r, tree);
 }
 
+struct paths_and_oids {
+   struct string_list list;
+};
+
+static void paths_and_oids_init(struct paths_and_oids *po)
+{
+   string_list_init(>list, 1);
+}
+
+static void 

[PATCH v2 3/6] pack-objects: add --sparse option

2018-11-29 Thread Derrick Stolee via GitGitGadget
From: Derrick Stolee 

Add a '--sparse' option flag to the pack-objects builtin. This
allows the user to specify that they want to use the new logic
for walking trees. This logic currently does not differ from the
existing output, but will in a later change.

Create a new test script, t5322-pack-objects-sparse.sh, to ensure
the object list that is selected matches what we expect. When we
update the logic to walk in a sparse fashion, the final test will
be updated to show the extra objects that are added.

Signed-off-by: Derrick Stolee 
---
 Documentation/git-pack-objects.txt |   9 ++-
 builtin/pack-objects.c |   5 +-
 t/t5322-pack-objects-sparse.sh | 115 +
 3 files changed, 127 insertions(+), 2 deletions(-)
 create mode 100755 t/t5322-pack-objects-sparse.sh

diff --git a/Documentation/git-pack-objects.txt 
b/Documentation/git-pack-objects.txt
index 40c825c381..ced2630eb3 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -14,7 +14,7 @@ SYNOPSIS
[--local] [--incremental] [--window=] [--depth=]
[--revs [--unpacked | --all]] [--keep-pack=]
[--stdout [--filter=] | base-name]
-   [--shallow] [--keep-true-parents] < object-list
+   [--shallow] [--keep-true-parents] [--sparse] < object-list
 
 
 DESCRIPTION
@@ -196,6 +196,13 @@ depth is 4095.
Add --no-reuse-object if you want to force a uniform compression
level on all data no matter the source.
 
+--sparse::
+   Use the "sparse" algorithm to determine which objects to include in
+   the pack. This can have significant performance benefits when computing
+   a pack to send a small change. However, it is possible that extra
+   objects are added to the pack-file if the included commits contain
+   certain types of direct renames.
+
 --thin::
Create a "thin" pack by omitting the common objects between a
sender and a receiver in order to reduce network transfer. This
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 5f70d840a7..7d5b0735e3 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -84,6 +84,7 @@ static unsigned long pack_size_limit;
 static int depth = 50;
 static int delta_search_threads;
 static int pack_to_stdout;
+static int sparse;
 static int thin;
 static int num_preferred_base;
 static struct progress *progress_state;
@@ -3135,7 +3136,7 @@ static void get_object_list(int ac, const char **av)
 
if (prepare_revision_walk())
die(_("revision walk setup failed"));
-   mark_edges_uninteresting(, show_edge, 0);
+   mark_edges_uninteresting(, show_edge, sparse);
 
if (!fn_show_object)
fn_show_object = show_object;
@@ -3292,6 +3293,8 @@ int cmd_pack_objects(int argc, const char **argv, const 
char *prefix)
{ OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"),
  N_("unpack unreachable objects newer than "),
  PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
+   OPT_BOOL(0, "sparse", ,
+N_("use the sparse reachability algorithm")),
OPT_BOOL(0, "thin", ,
 N_("create thin packs")),
OPT_BOOL(0, "shallow", ,
diff --git a/t/t5322-pack-objects-sparse.sh b/t/t5322-pack-objects-sparse.sh
new file mode 100755
index 00..81f6805bc3
--- /dev/null
+++ b/t/t5322-pack-objects-sparse.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+
+test_description='pack-objects object selection using sparse algorithm'
+. ./test-lib.sh
+
+test_expect_success 'setup repo' '
+   test_commit initial &&
+   for i in $(test_seq 1 3)
+   do
+   mkdir f$i &&
+   for j in $(test_seq 1 3)
+   do
+   mkdir f$i/f$j &&
+   echo $j >f$i/f$j/data.txt
+   done
+   done &&
+   git add . &&
+   git commit -m "Initialized trees" &&
+   for i in $(test_seq 1 3)
+   do
+   git checkout -b topic$i master &&
+   echo change-$i >f$i/f$i/data.txt &&
+   git commit -a -m "Changed f$i/f$i/data.txt"
+   done &&
+   cat >packinput.txt <<-EOF &&
+   topic1
+   ^topic2
+   ^topic3
+   EOF
+   git rev-parse   \
+   topic1  \
+   topic1^{tree}   \
+   topic1:f1   \
+   topic1:f1/f1\
+   topic1:f1/f1/data.txt | sort >expect_objects.txt
+'
+
+test_expect_success 'non-sparse pack-objects' '
+   git pack-objects --stdout --revs nonsparse.pack &&
+   git index-pack -o nonsparse.idx nonsparse.pack &&
+   git show-index nonsparse_objects.txt &&
+   test_cmp expect_objects.txt nonsparse_objects.txt
+'
+
+test_expect_success 'sparse pack-objects' '
+   git pack-objects --stdout --revs --sparse sparse.pack &&
+ 

Re: [PATCH 3/5] pack-objects: add --sparse option

2018-11-29 Thread Derrick Stolee

On 11/28/2018 5:11 PM, Stefan Beller wrote:

+--sparse::
+   Use the "sparse" algorithm to determine which objects to include in
+   the pack. This can have significant performance benefits when computing
+   a pack to send a small change. However, it is possible that extra
+   objects are added to the pack-file if the included commits contain
+   certain types of direct renames.

As a user, where do I find a discussion of these walking algorithms?
(i.e. how can I tell if I can really expect to gain performance benefits,
what are the tradeoffs? "If it were strictly better than the original,
it would be on by default" might be a thought of a user)


You're right that having this hidden as an opt-in config variable makes 
it hard to discover as a typical user.


I would argue that we should actually make the config setting true by 
default, and recommend that servers opt-out. Here are my reasons:


1. The vast majority of users are clients.

2. Client users are not likely to know about and tweak these settings.

3. Server users are more likely to keep an eye on the different knobs 
they can tweak.


4. Servers should use the reachability bitmaps, which don't use this 
logic anyway.


While _eventually_ we should make this opt-out, we shouldn't do that 
until it has cooked a while.


Thanks,
-Stolee


Re: [PATCH] rebase: mark the C reimplementation as an experimental opt-in feature (was Re: [ANNOUNCE] Git v2.20.0-rc1)

2018-11-29 Thread Johannes Schindelin
Hi Jonathan,

if you could pry more information (or better information) out of that bug
reporter, that would be nice. Apparently my email address is blacklisted
by his mail provider, so he is unlikely to have received my previous mail
(nor will he receive this one, I am sure).

Thanks,
Dscho

On Wed, 28 Nov 2018, Johannes Schindelin wrote:

> Hi Jonathan,
> 
> On Tue, 27 Nov 2018, Jonathan Nieder wrote:
> 
> > At https://bugs.debian.org/914695 is a report of a test regression in
> > an outside project that is very likely to have been triggered by the
> > new faster rebase code.
> 
> From looking through that log.gz (without having a clue where the test
> code lives, so I cannot say what it is supposed to do, and also: this is
> the first time I hear about dgit...), it would appear that this must be a
> regression in the reflog messages produced by `git rebase`.
> 
> > The issue has not been triaged, so I don't know yet whether it's a
> > problem in rebase-in-c or a manifestation of a bug in the test.
> 
> It ends thusly:
> 
> -- snip --
> [...]
> + git reflog
> + egrep 'debrebase new-upstream.*checkout'
> + test 1 = 0
> + t-report-failure
> + set +x
> TEST FAILED
> -- snap --
> 
> Which makes me think that the reflog we produce in *some* code path that
> originally called `git checkout` differs from the scripted rebase's
> generated reflog.
> 
> > That said, Google has been running with the new rebase since ~1 month
> > ago when it became the default, with no issues reported by users.  As a
> > result, I am confident that it can cope with what most users of "next"
> > throw at it, which means that if we are to find more issues to polish it
> > better, it will need all the exposure it can get.
> 
> Right. And there are a few weeks before the holidays, which should give me
> time to fix whatever bugs are discovered (I only half mind being the only
> one who fixes these bugs).
> 
> > In the Google deployment, we will keep using rebase-in-c even if it
> > gets disabled by default, in order to help with that.
> > 
> > From the Debian point of view, it's only a matter of time before
> > rebase-in-c becomes the default: even if it's not the default in 2.20,
> > it would presumably be so in 2.21 or 2.22.  That means the community's
> > attention when resolving security and reliability bugs would be on the
> > rebase-in-c implementation.  As a result, the Debian package will most
> > likely enable rebase-in-c by default even if upstream disables it, in
> > order to increase the package's shelf life (i.e. to ease the
> > maintenance burden of supporting whichever version of the package ends
> > up in the next Debian stable).
> > 
> > So with either hat on, it doesn't matter whether you apply this patch
> > upstream.
> > 
> > Having two pretty different deployments end up with the same
> > conclusion leads me to suspect that it's best for upstream not to
> > apply the revert patch, unless either
> > 
> >   (a) we have a concrete regression to address and then try again, or
> >   (b) we have a test or other plan to follow before trying again.
> 
> In this instance, I am more a fan of the "let's move fast and break
> things, then move even faster fixing them" approach.
> 
> Besides, the bug that Ævar discovered was a bug already in the scripted
> rebase, but hidden by yet another bug (the missing error checking).
> 
> I get the pretty firm impression that the common code paths are now pretty
> robust, and only lesser-exercised features may expose a bug (or
> regression, as in the case of the reflogs, where one could argue that the
> exact reflog message is not something we promise not to fiddle with).
> 
> Ciao,
> Dscho

Re: [PATCH v1] teach git to support a virtual (partially populated) work directory

2018-11-29 Thread Ben Peart



On 11/28/2018 8:31 AM, SZEDER Gábor wrote:

On Tue, Nov 27, 2018 at 02:50:57PM -0500, Ben Peart wrote:


diff --git a/t/t1092-virtualworkdir.sh b/t/t1092-virtualworkdir.sh
new file mode 100755
index 00..0cdfe9b362
--- /dev/null
+++ b/t/t1092-virtualworkdir.sh
@@ -0,0 +1,393 @@
+#!/bin/sh
+
+test_description='virtual work directory tests'
+
+. ./test-lib.sh
+
+# We need total control of the virtual work directory hook
+sane_unset GIT_TEST_VIRTUALWORKDIR
+
+clean_repo () {
+   rm .git/index &&
+   git -c core.virtualworkdir=false reset --hard HEAD &&
+   git -c core.virtualworkdir=false clean -fd &&
+   touch untracked.txt &&

We would usually run '>untracked.txt' instead, sparing the external
process.

A further nit is that a function called 'clean_repo' creates new
untracked files...


Thanks, all good suggestions I've incorporated for the next iteration.




+   touch dir1/untracked.txt &&
+   touch dir2/untracked.txt
+}
+
+test_expect_success 'setup' '
+   mkdir -p .git/hooks/ &&
+   cat > .gitignore <<-\EOF &&

CodingGuidelines suggest no space between redirection operator and
filename.


+   .gitignore
+   expect*
+   actual*
+   EOF
+   touch file1.txt &&
+   touch file2.txt &&
+   mkdir -p dir1 &&
+   touch dir1/file1.txt &&
+   touch dir1/file2.txt &&
+   mkdir -p dir2 &&
+   touch dir2/file1.txt &&
+   touch dir2/file2.txt &&
+   git add . &&
+   git commit -m "initial" &&
+   git config --local core.virtualworkdir true
+'



+test_expect_success 'verify files not listed are ignored by git clean -f -x' '
+   clean_repo &&

I find it odd to clean the repo right after setting it up; but then
again, 'clean_repo' not only cleans, but also creates new files.
Perhaps rename it to 'reset_repo'?  Dunno.


+   write_script .git/hooks/virtual-work-dir <<-\EOF &&
+   printf "untracked.txt\0"
+   printf "dir1/\0"
+   EOF
+   mkdir -p dir3 &&
+   touch dir3/untracked.txt &&
+   git clean -f -x &&
+   test -f file1.txt &&

Please use the 'test_path_is_file', ...


+   test -f file2.txt &&
+   test ! -f untracked.txt &&

... 'test_path_is_missing', and ...


+   test -d dir1 &&

... 'test_path_is_dir' helpers, respectively, because they print
informative error messages on failure.


+   test -f dir1/file1.txt &&
+   test -f dir1/file2.txt &&
+   test ! -f dir1/untracked.txt &&
+   test -f dir2/file1.txt &&
+   test -f dir2/file2.txt &&
+   test -f dir2/untracked.txt &&
+   test -d dir3 &&
+   test -f dir3/untracked.txt
+'


Re: [PATCH v1] mem_pool: add GIT_TRACE_MEMPOOL support

2018-11-29 Thread Ben Peart



On 11/28/2018 4:37 AM, Johannes Schindelin wrote:

Hi Ben,

On Tue, 27 Nov 2018, Ben Peart wrote:


From: Ben Peart 

Add tracing around initializing and discarding mempools. In discard report
on the amount of memory unused in the current block to help tune setting
the initial_size.

Signed-off-by: Ben Peart 
---

Looks good.

My only question: should we also trace calls to _alloc(), _calloc() and
_combine()?


I was trying to tune the initial size in my use of the mem_pool and so 
found this tracing useful to see how much memory was actually being 
used.  I'm inclined to only add tracing as it is needed rather that 
proactively because we think it _might_ be needed.  I suspect _alloc() 
and _calloc() would get very noisy and not add much value.




Ciao,
Johannes


Notes:
 Base Ref: * git-trace-mempool
 Web-Diff: https://github.com/benpeart/git/commit/9ac84bbca2
 Checkout: git fetch https://github.com/benpeart/git git-trace-mempool-v1 
&& git checkout 9ac84bbca2

  mem-pool.c | 5 +
  1 file changed, 5 insertions(+)

diff --git a/mem-pool.c b/mem-pool.c
index a2841a4a9a..065389aaec 100644
--- a/mem-pool.c
+++ b/mem-pool.c
@@ -5,6 +5,7 @@
  #include "cache.h"
  #include "mem-pool.h"
  
+static struct trace_key trace_mem_pool = TRACE_KEY_INIT(MEMPOOL);

  #define BLOCK_GROWTH_SIZE 1024*1024 - sizeof(struct mp_block);
  
  /*

@@ -48,12 +49,16 @@ void mem_pool_init(struct mem_pool **mem_pool, size_t 
initial_size)
mem_pool_alloc_block(pool, initial_size, NULL);
  
  	*mem_pool = pool;

+   trace_printf_key(_mem_pool, "mem_pool (%p): init (%"PRIuMAX") initial 
size\n",
+   pool, (uintmax_t)initial_size);
  }
  
  void mem_pool_discard(struct mem_pool *mem_pool, int invalidate_memory)

  {
struct mp_block *block, *block_to_free;
  
+	trace_printf_key(_mem_pool, "mem_pool (%p): discard (%"PRIuMAX") unused\n",

+   mem_pool, (uintmax_t)(mem_pool->mp_block->end - 
mem_pool->mp_block->next_free));
block = mem_pool->mp_block;
while (block)
{

base-commit: bb75be6cb916297f271c846f2f9caa3daaaec718
--
2.18.0.windows.1




Re: [PATCH v11 00/22] Convert "git stash" to C builtin

2018-11-29 Thread Johannes Schindelin
Hi Junio,

On Thu, 29 Nov 2018, Johannes Schindelin wrote:

> On Mon, 26 Nov 2018, Junio C Hamano wrote:
> 
> > Junio C Hamano  writes:
> > 
> > > Thomas Gummerer  writes:
> > >
> > >> Thanks for your work on this!  I have read through the range-diff and
> > >> the new patch of this last round, and this addresses all the comments
> > >> I had on v10 (and some more :)).  I consider it
> > >> Reviewed-by: Thomas Gummerer 
> > >
> > > Thanks.
> > >
> > > One thing that bothers me is that this seems to have been rebased on
> > > 'master', but as long as we are rebasing, the updated series must
> > > also take into account of the sd/stash-wo-user-name topic, i.e. if
> > > we are rebasing it, it should be rebased on top of the result of
> > >
> > >   git checkout -B ps/rebase-in-c master
> > >   git merge --no-ff sd/stash-wo-user-name
> > >
> > > I think.
> > 
> > https://travis-ci.org/git/git/builds/459619672 would show that this
> > C reimplementation now regresses from the scripted version due to
> > lack of such rebasing (i.e. porting a correction from scripted one).
> 
> Oh, you know, at first I *mis-read* your mail to mean "don't you rebase
> all the time!", but in this case (in contrast to earlier statements about
> rebasing between iterations of patch series), you *do* want Paul to
> rebase.
> 
> Let me see what I can come up with in my `git-stash` branch on
> https://github.com/dscho/git

There. I force-pushed an update that is based on sd/stash-wo-user-name and
adds a `prepare_fallback_ident(name, email)` to `ident.c` for use in the
built-in stash:

https://github.com/dscho/git/commit/d37ce623fbd32e4345c701dea822e56de1a5417f

It passes t3903 in a little over a minute with
GIT_TEST_STASH_USE_BUILTIN=true and in a little less than seven minutes
with GIT_TEST_STASH_USE_BUILTIN=false.

Ciao,
Dscho



Re: Git Tags

2018-11-29 Thread Mateusz Loskot
On Thu, 29 Nov 2018 at 14:40, Randall S. Becker  wrote:
> On November 29, 2018 6:56, Mateusz Loskot wrote:
> > On Thu, 29 Nov 2018 at 12:50, Stefanie Leisestreichler 
> >  wrote:
> > >
> > > git tag -a 0.9.0
> > > git push origin master
> > >
> > > In my local repository, when I run "git tag" it is showing me "0.9.0".
> > >
> > > Then I did (on box B)
> > > git clone ssh://user@host:/path/project.git cd project git tag
> > >
> > > Now git tag is showing nothing.
> > >
> > > Why is the tag only available in my local repository?
> >
> > >From https://git-scm.com/book/en/v2/Git-Basics-Tagging
> > "By default, the git push command doesn’t transfer tags to remote servers.
> > You will have to explicitly push tags to a shared server after you have 
> > created
> > them."
>
> git push --tags
>

After my yesterday experience [1], I'd be careful with git push --tags :)

[1] genuine screenshot and link to related thread at
https://twitter.com/mloskot/status/1068072285846859776

Best regards,
-- 
Mateusz Loskot, http://mateusz.loskot.net


RE: Git Tags

2018-11-29 Thread Randall S. Becker
On November 29, 2018 6:56, Mateusz Loskot wrote:
> On Thu, 29 Nov 2018 at 12:50, Stefanie Leisestreichler
>  wrote:
> >
> > git tag -a 0.9.0
> > git push origin master
> >
> > In my local repository, when I run "git tag" it is showing me "0.9.0".
> >
> > Then I did (on box B)
> > git clone ssh://user@host:/path/project.git cd project git tag
> >
> > Now git tag is showing nothing.
> >
> > Why is the tag only available in my local repository?
> 
> >From https://git-scm.com/book/en/v2/Git-Basics-Tagging
> "By default, the git push command doesn’t transfer tags to remote servers.
> You will have to explicitly push tags to a shared server after you have 
> created
> them."

git push --tags

and

git fetch --tags

to be symmetrical

Cheers,
Randall

-- Brief whoami:
 NonStop developer since approximately 2112884442
 UNIX developer since approximately 421664400
-- In my real life, I talk too much.



Re: [bug report] git-gui child windows are blank

2018-11-29 Thread Kenn Sebesta
Just checked gitk, it seems to work fine including children windows.
This problem seems to affect git-gui only.
On Thu, Nov 29, 2018 at 5:16 AM Eric Sunshine  wrote:
>
> On Wed, Nov 28, 2018 at 2:29 PM Stefan Beller  wrote:
> > On Wed, Nov 28, 2018 at 6:13 AM Kenn Sebesta  wrote:
> > > v2.19.2, installed from brew on macOS Mojave 14.2.1.
> > >
> > > `git-gui` is my much beloved go-to tool for everything git.
> > > Unfortunately, on my new Macbook Air it seems to have a bug. When I
> > > first load the program, the parent window populates normally with the
> > > stage/unstaged and diff panes. However, when I click Push, the child
> > > window is completely blank. The frame is there, but there is no
> > > content.
> >
> > Looking through the mailing list archive, this
> > seemed to be one of the last relevant messges
> > https://public-inbox.org/git/20180724065120.7664-1-sunsh...@sunshineco.com/
>
> I was hoping that Junio would patch-monkey that one since that
> crash-at-launch makes gitk unusable for Mojave users, but apparently
> it never got picked up.
>
> Anyhow, the issue fixed by that patch has to do with 'osascript' on
> Apple, and it's the only such invocation in the source code of
> gitk/git-gui. The 'osascript' invocation merely attempts to foreground
> the application at launch, so is almost certainly unrelated to the
> above reported behavior. Somebody running Mojave will likely need to
> spend some time debugging it. (Unfortunately, I'm a couple major
> releases behind and don't plan on upgrading.)


[PATCH v2 0/1] Fix git rebase --stat -i

2018-11-29 Thread Johannes Schindelin via GitGitGadget
We're really entering obscure territory here, I would say.

To trigger the bug, two things have to come together: the user must have
asked for a diffstat afterwards, and the commits need to have been rebased
onto a completely unrelated commit history (i.e. there must exist no merge
base between the pre-rebase HEAD and the post-rebase HEAD).

Please note that this bug existed already in the scripted rebase, but it was
never detected because the scripted version would not even perform any error
checking.

It will make Junio very happy that I squashed the regression test in to the
patch that fixes it. The reason, however, was not to make Junio happy (I
hope to make him happy by fixing bugs), but simply that an earlier iteration
of test would only fail with the built-in rebase, but not with the scripted
version. The current version would fail with the scripted version, but I'll
save the time to split the patch again now.

Changes since v1:

 * The commit message now talks more about what we should do in case that
   there is no merge base, rather than stressing the differences between the
   way scripted vs built-in rebase handled it (both buggy, and fixed by this
   patch).
 * In case that there is no merge base, it no longer reports "Changes from
   (empty) to ..." but "Changes to ...", which should be a lot less
   controversial.

Johannes Schindelin (1):
  rebase --stat: fix when rebasing to an unrelated history

 builtin/rebase.c  | 18 --
 git-legacy-rebase.sh  | 10 --
 t/t3406-rebase-message.sh | 10 ++
 3 files changed, 30 insertions(+), 8 deletions(-)


base-commit: a1598010f775d82b5adf12c29d0f5bc9b41434c6
Published-As: 
https://github.com/gitgitgadget/git/releases/tags/pr-88%2Fdscho%2Frebase-stat-fix-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git 
pr-88/dscho/rebase-stat-fix-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/88

Range-diff vs v1:

 1:  680385e4bd ! 1:  190c7856ad rebase --stat: fix when rebasing to an 
unrelated history
 @@ -3,22 +3,21 @@
  rebase --stat: fix when rebasing to an unrelated history
  
  When rebasing to a commit history that has no common commits with the
 -current branch, there is no merge base. The scripted version of the 
`git
 -rebase` command was not prepared for that and spewed out
 +current branch, there is no merge base. In diffstat mode, this means
 +that we cannot compare to the merge base, but we have to compare to 
the
 +empty tree instead.
  
 -fatal: ambiguous argument '': unknown revision or path not in
 -the working tree.
 +Also, if running in verbose diffstat mode, we should not output
  
 -but then continued (due to lack of error checking).
 +Changes from  to 
  
 -The built-in version of the `git rebase` command blindly translated 
that
 -shell script code, assuming that there is no need to test whether 
there
 -*was* a merge base, and due to its better error checking, exited with 
a
 -fatal error (because it tried to read the object with hash ...
 -as a tree).
 +as that does not make sense without any merge base.
  
 -Fix both scripted and built-in versions to output something sensibly,
 -and add a regression test to keep this working in all eternity.
 +Note: neither scripted nor built-in versoin of `git rebase` were
 +prepared for this situation well. We use this opportunity not only to
 +fix the bug(s), but also to make both versions' output consistent in
 +this instance. And add a regression test to keep this working in all
 +eternity.
  
  Reported-by: Ævar Arnfjörð Bjarmason 
  Signed-off-by: Johannes Schindelin 
 @@ -27,15 +26,25 @@
  --- a/builtin/rebase.c
  +++ b/builtin/rebase.c
  @@
 +  if (options.flags & REBASE_DIFFSTAT) {
 +  struct diff_options opts;
   
 -  if (options.flags & REBASE_VERBOSE)
 -  printf(_("Changes from %s to %s:\n"),
 +- if (options.flags & REBASE_VERBOSE)
 +- printf(_("Changes from %s to %s:\n"),
  - oid_to_hex(_base),
 -+ is_null_oid(_base) ?
 -+ "(empty)" : oid_to_hex(_base),
 -  oid_to_hex(>object.oid));
 +- oid_to_hex(>object.oid));
 ++ if (options.flags & REBASE_VERBOSE) {
 ++ if (is_null_oid(_base))
 ++ printf(_("Changes to %s:\n"),
 ++oid_to_hex(>object.oid));
 ++ else
 ++ printf(_("Changes from %s to %s:\n"),
 ++oid_to_hex(_base),
 ++ 

[PATCH v2 1/1] rebase --stat: fix when rebasing to an unrelated history

2018-11-29 Thread Johannes Schindelin via GitGitGadget
From: Johannes Schindelin 

When rebasing to a commit history that has no common commits with the
current branch, there is no merge base. In diffstat mode, this means
that we cannot compare to the merge base, but we have to compare to the
empty tree instead.

Also, if running in verbose diffstat mode, we should not output

Changes from  to 

as that does not make sense without any merge base.

Note: neither scripted nor built-in versoin of `git rebase` were
prepared for this situation well. We use this opportunity not only to
fix the bug(s), but also to make both versions' output consistent in
this instance. And add a regression test to keep this working in all
eternity.

Reported-by: Ævar Arnfjörð Bjarmason 
Signed-off-by: Johannes Schindelin 
---
 builtin/rebase.c  | 18 --
 git-legacy-rebase.sh  | 10 --
 t/t3406-rebase-message.sh | 10 ++
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5b3e5baec8..1c6f817f4b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1481,10 +1481,15 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
if (options.flags & REBASE_DIFFSTAT) {
struct diff_options opts;
 
-   if (options.flags & REBASE_VERBOSE)
-   printf(_("Changes from %s to %s:\n"),
-   oid_to_hex(_base),
-   oid_to_hex(>object.oid));
+   if (options.flags & REBASE_VERBOSE) {
+   if (is_null_oid(_base))
+   printf(_("Changes to %s:\n"),
+  oid_to_hex(>object.oid));
+   else
+   printf(_("Changes from %s to %s:\n"),
+  oid_to_hex(_base),
+  oid_to_hex(>object.oid));
+   }
 
/* We want color (if set), but no pager */
diff_setup();
@@ -1494,8 +1499,9 @@ int cmd_rebase(int argc, const char **argv, const char 
*prefix)
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
opts.detect_rename = DIFF_DETECT_RENAME;
diff_setup_done();
-   diff_tree_oid(_base, >object.oid,
- "", );
+   diff_tree_oid(is_null_oid(_base) ?
+ the_hash_algo->empty_tree : _base,
+ >object.oid, "", );
diffcore_std();
diff_flush();
}
diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh
index b97ffdc9dd..b4c7dbfa57 100755
--- a/git-legacy-rebase.sh
+++ b/git-legacy-rebase.sh
@@ -718,10 +718,16 @@ if test -n "$diffstat"
 then
if test -n "$verbose"
then
-   echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+   if test -z "$mb"
+   then
+   echo "$(eval_gettext "Changes to \$onto:")"
+   else
+   echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+   fi
fi
+   mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
# We want color (if set), but no pager
-   GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
+   GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
 fi
 
 test -n "$interactive_rebase" && run_specific_rebase
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 38bd876cab..c2c9950568 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -91,4 +91,14 @@ test_expect_success 'error out early upon -C or 
--whitespace=' '
test_i18ngrep "Invalid whitespace option" err
 '
 
+test_expect_success 'rebase -i onto unrelated history' '
+   git init unrelated &&
+   test_commit -C unrelated 1 &&
+   git -C unrelated remote add -f origin "$PWD" &&
+   git -C unrelated branch --set-upstream-to=origin/master &&
+   git -C unrelated -c core.editor=true rebase -i -v --stat >actual &&
+   test_i18ngrep "Changes to " actual &&
+   test_i18ngrep "5 files changed" actual
+'
+
 test_done
-- 
gitgitgadget


Re: [PATCH v11 00/22] Convert "git stash" to C builtin

2018-11-29 Thread Johannes Schindelin
Hi Junio,

On Mon, 26 Nov 2018, Junio C Hamano wrote:

> Junio C Hamano  writes:
> 
> > Thomas Gummerer  writes:
> >
> >> Thanks for your work on this!  I have read through the range-diff and
> >> the new patch of this last round, and this addresses all the comments
> >> I had on v10 (and some more :)).  I consider it
> >> Reviewed-by: Thomas Gummerer 
> >
> > Thanks.
> >
> > One thing that bothers me is that this seems to have been rebased on
> > 'master', but as long as we are rebasing, the updated series must
> > also take into account of the sd/stash-wo-user-name topic, i.e. if
> > we are rebasing it, it should be rebased on top of the result of
> >
> > git checkout -B ps/rebase-in-c master
> > git merge --no-ff sd/stash-wo-user-name
> >
> > I think.
> 
> https://travis-ci.org/git/git/builds/459619672 would show that this
> C reimplementation now regresses from the scripted version due to
> lack of such rebasing (i.e. porting a correction from scripted one).

Oh, you know, at first I *mis-read* your mail to mean "don't you rebase
all the time!", but in this case (in contrast to earlier statements about
rebasing between iterations of patch series), you *do* want Paul to
rebase.

Let me see what I can come up with in my `git-stash` branch on
https://github.com/dscho/git

Ciao,
Dscho


Re: [PATCH 1/1] rebase --stat: fix when rebasing to an unrelated history

2018-11-29 Thread Johannes Schindelin
Hi Junio,

On Thu, 29 Nov 2018, Junio C Hamano wrote:

> "Johannes Schindelin via GitGitGadget" 
> writes:
> 
> > The built-in version of the `git rebase` command blindly translated that
> > shell script code, assuming that there is no need to test whether there
> > *was* a merge base, and due to its better error checking, exited with a
> > fatal error (because it tried to read the object with hash ...
> > as a tree).
> 
> And the scripted version produced a wrong result because it did not
> check the lack of merge base and fed an empty string (presumably, as
> that is what you would get from mb=$(merge-base A B) when A and B
> are unrelated) to later steps?  If that is the case, then it *is* a
> very significant thing to record here.  As it was not merely "failed
> to stop due to lack of error checking", but a lot worse.  It was
> producing a wrong result.

Indeed. But it was only in the `--stat` reporting, so it did not produce
an incorrect rebased history.

> A more faithful reimplementation would not have exited with fatal
> error, but would have produced the same wrong result, so "a better
> error checking caused the reimplementation die where the original
> did not die" may be correct but is much less important than the fact
> that "the logic used in the original to produce diffstat forgot that
> there may not be a merge base and would not have worked correctly in
> such a case, and that is what we are correcting" is more important.

True.

> Please descibe the issue as such, if that is the case (I cannot read
> from the description in the proposed log message if that is the
> case---but I came to the conclusion that it is what you wanted to
> fix reading the code).

Indeed, my commit message is a bit too close to what I fixed, and not
enough about what needed to be fixed.

> > if (options.flags & REBASE_VERBOSE)
> > printf(_("Changes from %s to %s:\n"),
> > -   oid_to_hex(_base),
> > +   is_null_oid(_base) ?
> > +   "(empty)" : oid_to_hex(_base),
> 
> I am not sure (empty) is a good idea for two reasons.  It is going
> to be inserted into an translated string without translation.

Oooops.

> Also it is too similar to the fallback string used by some printf
> implementations when NULL was given to %s by mistake.

You mean `(null)`? That was actually intentional, I just thought that
`(empty)` would be different enough...

> If there weren't i18n issues, I would suggest to use "empty merge
> base" or "empty tree" instead, but the old one would have shown
> 0{40}, so perhaps empty_tree_oid_hex() is a good substitute?

As this is a user-facing message, I'd rather avoid something like
`empty_tree_oid_hex()`, which to every Git user who does not happen to be
a Git developer, too, must sound very cryptic.

But I guess that I should not be so lazy and really use two different
messages here:

Changes from  to 

and if there is no merge base,

Changes in 

Will fix.

> > @@ -1494,8 +1495,9 @@ int cmd_rebase(int argc, const char **argv, const 
> > char *prefix)
> > DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
> > opts.detect_rename = DIFF_DETECT_RENAME;
> > diff_setup_done();
> > -   diff_tree_oid(_base, >object.oid,
> > - "", );
> > +   diff_tree_oid(is_null_oid(_base) ?
> > + the_hash_algo->empty_tree : _base,
> > + >object.oid, "", );
> 
> The original would have run "git diff '' $onto", and died with an
> error message, so both the original and the reimplementation were
> failing.  Just in different ways ;-)

Right.

> > diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh
> > index b97ffdc9dd..be3b241676 100755
> > --- a/git-legacy-rebase.sh
> > +++ b/git-legacy-rebase.sh
> > @@ -718,10 +718,12 @@ if test -n "$diffstat"
> >  then
> > if test -n "$verbose"
> > then
> > -   echo "$(eval_gettext "Changes from \$mb to \$onto:")"
> > +   mb_display="${mb:-(empty)}"
> > +   echo "$(eval_gettext "Changes from \$mb_display to \$onto:")"
> > fi
> > +   mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
> > # We want color (if set), but no pager
> > -   GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
> > +   GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
> 
> Code fix for diff-tree invocation, both in the builtin/ version and
> this one, looks correct.

Okay. I fixed the two things you pointed out, just waiting for the Linux
phase to finish (I don't think there is anything OS-specific in this
patch, so I trust macOS and Windows to pass if Linux passes):
https://git-for-windows.visualstudio.com/git/_build/results?buildId=26116

Ciao,
Dscho


Hello

2018-11-29 Thread johann Reimann
Good day,

My Name is Johann Reimann and i have something important to discuss with you 
but only with your permission i will proceed.

Regards
J. Reimann


Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Johannes Schindelin
Hi Ævar,

On Thu, 29 Nov 2018, Ævar Arnfjörð Bjarmason wrote:

> On Thu, Nov 29 2018, Johannes Schindelin wrote:
> 
> > On Wed, 28 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
> >
> >> Change the semantics of the "--range-diff" option so that the regular
> >> diff options can be provided separately for the range-diff and the
> >> patch. This allows for supplying e.g. --range-diff-U0 and -U1 to
> >> "format-patch" to provide different context for the range-diff and the
> >> patch. This wasn't possible before.
> >
> > I really, really dislike the `--range-diff-`. We have
> > precedent for passing optional arguments that are passed to some other
> > command, so a much more logical and consistent convention would be to use
> > `--range-diff[=..]`, allowing all of the diff options that
> > you might want to pass to the outer diff in one go rather than having a
> > lengthy string of `--range-diff-this` and `--range-diff-that` options.
> 
> Where do we pass those sorts of arguments?
> 
> Reasons I did it this way:
> 
>  a) Passing it as one option will require the user to double-quote those
> options that take quoted arguments (e.g. --word-diff-regex), which I
> thought sucked more than the prefix. On the implementation side we
> couldn't leave the parsing of the command-line to the shell anymore.
> 
>  b) I think people will want to tweak this very rarely, much more rarely
> than e.g. -U10 in format-patch itself, so having something long-ish
> doesn't sound bad.

Hmm. I still don't like it. It sets a precedent, and we simply do not do
it that way in other circumstances (most obvious would be the -X merge
options). The more divergent user interfaces for the same sort of thing
are, the more brain cycles you force users to spend on navigating said
interfaces.

> > I only had time to skim the patch, and I have to wonder why you pass
> > around full-blown `rev_info` structs for range diff (and with that really
> > awful name `rd_rev`) rather than just the `diff_options` that you
> > *actually* care about?
> 
> Because setup_revisions() which does all the command-line parsing needs
> a rev_info, so even if we only need the diffopt in the end we need to
> initiate the whole thing.
> 
> Suggestions for a better varibale name most welcome.

`range_diff_revs`

And you do not need to pass around the whole thing. You can easily pass
`_diff_revs.diffopt`.

Don't pass around what you do not need to pass around.

Ciao,
Dscho

> 
> > Ciao,
> > Dscho
> >
> >>
> >> Ever since the "--range-diff" option was added in
> >> 31e2617a5f ("format-patch: add --range-diff option to embed diff in
> >> cover letter", 2018-07-22) the "rev->diffopt" we pass down to the diff
> >> machinery has been the one we get from "format-patch"'s own
> >> setup_revisions().
> >>
> >> This sort of thing is unique among the log-like commands in
> >> builtin/log.c, no command than format-patch will embed the output of
> >> another log-like command. Since the "rev->diffopt" is reused we need
> >> to munge it before we pass it to show_range_diff(). See
> >> 43dafc4172 ("format-patch: don't include --stat with --range-diff
> >> output", 2018-11-22) for a related regression fix which is being
> >> mostly reverted here.
> >>
> >> Implementation notes: 1) We're not bothering with the full teardown
> >> around die() and will leak memory, but it's too much boilerplate to do
> >> all the frees with/without the die() and not worth it. 2) We call
> >> repo_init_revisions() for "rd_rev" even though we could get away with
> >> a shallow copy like the code we're replacing (and which
> >> show_range_diff() itself does). This is to make this code more easily
> >> understood.
> >>
> >> Signed-off-by: Ævar Arnfjörð Bjarmason 
> >> ---
> >>  Documentation/git-format-patch.txt | 10 ++-
> >>  builtin/log.c  | 42 +++---
> >>  t/t3206-range-diff.sh  | 41 +
> >>  3 files changed, 82 insertions(+), 11 deletions(-)
> >>
> >> diff --git a/Documentation/git-format-patch.txt 
> >> b/Documentation/git-format-patch.txt
> >> index aba4c5febe..6c048f415f 100644
> >> --- a/Documentation/git-format-patch.txt
> >> +++ b/Documentation/git-format-patch.txt
> >> @@ -24,7 +24,8 @@ SYNOPSIS
> >>   [--to=] [--cc=]
> >>   [--[no-]cover-letter] [--quiet] [--notes[=]]
> >>   [--interdiff=]
> >> - [--range-diff= [--creation-factor=]]
> >> + [--range-diff= [--creation-factor=]
> >> +[--range-diff]]
> >>   [--progress]
> >>   []
> >>   [  |  ]
> >> @@ -257,6 +258,13 @@ feeding the result to `git send-email`.
> >>creation/deletion cost fudge factor. See linkgit:git-range-diff[1])
> >>for details.
> >>
> >> +--range-diff::
> >> +  Other options prefixed with `--range-diff` are stripped of
> >> +  that prefix and passed as-is to the diff machinery used to
> >> +  generate the range-diff, 

Re: Git Tags

2018-11-29 Thread Mateusz Loskot
On Thu, 29 Nov 2018 at 12:50, Stefanie Leisestreichler
 wrote:
>
> git tag -a 0.9.0
> git push origin master
>
> In my local repository, when I run "git tag" it is showing me "0.9.0".
>
> Then I did (on box B)
> git clone ssh://user@host:/path/project.git
> cd project
> git tag
>
> Now git tag is showing nothing.
>
> Why is the tag only available in my local repository?

>From https://git-scm.com/book/en/v2/Git-Basics-Tagging
"By default, the git push command doesn’t transfer tags to remote servers.
You will have to explicitly push tags to a shared server after you
have created them."

Best regards,
-- 
Mateusz Loskot, http://mateusz.loskot.net


Git Tags

2018-11-29 Thread Stefanie Leisestreichler

Hi.

I have done this (on box A):

git commit -m "Message"
git tag -a 0.9.0
git push origin master

In my local repository, when I run "git tag" it is showing me "0.9.0".

Then I did (on box B)
git clone ssh://user@host:/path/project.git
cd project
git tag

Now git tag is showing nothing.

Why is the tag only available in my local repository?

Also when I try to
git clone --branch 0.9.0 ssh://user@host:/path/project.git
it tells me: fatal:remote branch not found in upstream repository origin

Why is the tag not available in origin?

Thanks,
Stefanie



Re: [PATCH] rebase -i: introduce the 'test' command

2018-11-29 Thread Johannes Schindelin
Hi Paul,

On Thu, 29 Nov 2018, Johannes Schindelin wrote:

> I already added a test... See the reschedule-failed-exec branch on
> https://github.com/dscho/git.

And now I put up a proper Pull Request, to be submitted via GitGitGadget
right after Git v2.20.0 will be released (technically, we are in a
feature freeze period right now, I just could no resist, as I found your
reasoning for rescheduling failed `exec` commands compelling, and there
were no `rebase` bugs for me to fix).

https://github.com/gitgitgadget/git/pull/90

Ciao,
Johannes


Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Ævar Arnfjörð Bjarmason


On Thu, Nov 29 2018, Johannes Schindelin wrote:

> Hi Ævar,
>
> On Wed, 28 Nov 2018, Ævar Arnfjörð Bjarmason wrote:
>
>> Change the semantics of the "--range-diff" option so that the regular
>> diff options can be provided separately for the range-diff and the
>> patch. This allows for supplying e.g. --range-diff-U0 and -U1 to
>> "format-patch" to provide different context for the range-diff and the
>> patch. This wasn't possible before.
>
> I really, really dislike the `--range-diff-`. We have
> precedent for passing optional arguments that are passed to some other
> command, so a much more logical and consistent convention would be to use
> `--range-diff[=..]`, allowing all of the diff options that
> you might want to pass to the outer diff in one go rather than having a
> lengthy string of `--range-diff-this` and `--range-diff-that` options.

Where do we pass those sorts of arguments?

Reasons I did it this way:

 a) Passing it as one option will require the user to double-quote those
options that take quoted arguments (e.g. --word-diff-regex), which I
thought sucked more than the prefix. On the implementation side we
couldn't leave the parsing of the command-line to the shell anymore.

 b) I think people will want to tweak this very rarely, much more rarely
than e.g. -U10 in format-patch itself, so having something long-ish
doesn't sound bad.

> I only had time to skim the patch, and I have to wonder why you pass
> around full-blown `rev_info` structs for range diff (and with that really
> awful name `rd_rev`) rather than just the `diff_options` that you
> *actually* care about?

Because setup_revisions() which does all the command-line parsing needs
a rev_info, so even if we only need the diffopt in the end we need to
initiate the whole thing.

Suggestions for a better varibale name most welcome.

> Ciao,
> Dscho
>
>>
>> Ever since the "--range-diff" option was added in
>> 31e2617a5f ("format-patch: add --range-diff option to embed diff in
>> cover letter", 2018-07-22) the "rev->diffopt" we pass down to the diff
>> machinery has been the one we get from "format-patch"'s own
>> setup_revisions().
>>
>> This sort of thing is unique among the log-like commands in
>> builtin/log.c, no command than format-patch will embed the output of
>> another log-like command. Since the "rev->diffopt" is reused we need
>> to munge it before we pass it to show_range_diff(). See
>> 43dafc4172 ("format-patch: don't include --stat with --range-diff
>> output", 2018-11-22) for a related regression fix which is being
>> mostly reverted here.
>>
>> Implementation notes: 1) We're not bothering with the full teardown
>> around die() and will leak memory, but it's too much boilerplate to do
>> all the frees with/without the die() and not worth it. 2) We call
>> repo_init_revisions() for "rd_rev" even though we could get away with
>> a shallow copy like the code we're replacing (and which
>> show_range_diff() itself does). This is to make this code more easily
>> understood.
>>
>> Signed-off-by: Ævar Arnfjörð Bjarmason 
>> ---
>>  Documentation/git-format-patch.txt | 10 ++-
>>  builtin/log.c  | 42 +++---
>>  t/t3206-range-diff.sh  | 41 +
>>  3 files changed, 82 insertions(+), 11 deletions(-)
>>
>> diff --git a/Documentation/git-format-patch.txt 
>> b/Documentation/git-format-patch.txt
>> index aba4c5febe..6c048f415f 100644
>> --- a/Documentation/git-format-patch.txt
>> +++ b/Documentation/git-format-patch.txt
>> @@ -24,7 +24,8 @@ SYNOPSIS
>> [--to=] [--cc=]
>> [--[no-]cover-letter] [--quiet] [--notes[=]]
>> [--interdiff=]
>> -   [--range-diff= [--creation-factor=]]
>> +   [--range-diff= [--creation-factor=]
>> +  [--range-diff]]
>> [--progress]
>> []
>> [  |  ]
>> @@ -257,6 +258,13 @@ feeding the result to `git send-email`.
>>  creation/deletion cost fudge factor. See linkgit:git-range-diff[1])
>>  for details.
>>
>> +--range-diff::
>> +Other options prefixed with `--range-diff` are stripped of
>> +that prefix and passed as-is to the diff machinery used to
>> +generate the range-diff, e.g. `--range-diff-U0` and
>> +`--range-diff--no-color`. This allows for adjusting the format
>> +of the range-diff independently from the patch itself.
>> +
>>  --notes[=]::
>>  Append the notes (see linkgit:git-notes[1]) for the commit
>>  after the three-dash line.
>> diff --git a/builtin/log.c b/builtin/log.c
>> index 02d88fa233..7658e56ecc 100644
>> --- a/builtin/log.c
>> +++ b/builtin/log.c
>> @@ -1023,7 +1023,8 @@ static void show_diffstat(struct rev_info *rev,
>>  fprintf(rev->diffopt.file, "\n");
>>  }
>>
>> -static void make_cover_letter(struct rev_info *rev, int use_stdout,
>> +static void make_cover_letter(struct rev_info *rev, struct rev_info *rd_rev,
>> 

My Humble Request

2018-11-29 Thread Abel Brent
Dear Friend,

I am Abel Brent, a NATO soldier serving in Afghanistan. I and my 
Comrades, we are seeking your assistance to help us 
receive/invest our funds in your country in any lucrative 
business. Please if this proposal is acceptable by you, kindly 
respond back to me for more details.

Thanks and waiting to hear from you.

Abel.


Re: [bug report] git-gui child windows are blank

2018-11-29 Thread Eric Sunshine
On Wed, Nov 28, 2018 at 2:29 PM Stefan Beller  wrote:
> On Wed, Nov 28, 2018 at 6:13 AM Kenn Sebesta  wrote:
> > v2.19.2, installed from brew on macOS Mojave 14.2.1.
> >
> > `git-gui` is my much beloved go-to tool for everything git.
> > Unfortunately, on my new Macbook Air it seems to have a bug. When I
> > first load the program, the parent window populates normally with the
> > stage/unstaged and diff panes. However, when I click Push, the child
> > window is completely blank. The frame is there, but there is no
> > content.
>
> Looking through the mailing list archive, this
> seemed to be one of the last relevant messges
> https://public-inbox.org/git/20180724065120.7664-1-sunsh...@sunshineco.com/

I was hoping that Junio would patch-monkey that one since that
crash-at-launch makes gitk unusable for Mojave users, but apparently
it never got picked up.

Anyhow, the issue fixed by that patch has to do with 'osascript' on
Apple, and it's the only such invocation in the source code of
gitk/git-gui. The 'osascript' invocation merely attempts to foreground
the application at launch, so is almost certainly unrelated to the
above reported behavior. Somebody running Mojave will likely need to
spend some time debugging it. (Unfortunately, I'm a couple major
releases behind and don't plan on upgrading.)


Re: in 2.19.2 t0061-run-command FAILs if . is in $PATH

2018-11-29 Thread Johannes Schindelin
Hi Merijn and Junio,

On Thu, 29 Nov 2018, Junio C Hamano wrote:

> Johannes Schindelin  writes:
> 
> > -test_expect_success 'run_command is restricted to PATH' '
> > +test_lazy_prereq DOT_IN_PATH '
> > +   case ":$PATH:" in
> > +   *:.:*) true;;
> > +   *) false;;
> > +   esac
> > +'
> 
> An empty element in the colon-separated list also serves as an
> instruction to pick up executable from $cwd, so
> 
>   case ":$PATH:" in
>   *:.:** | *::*) true ;;
>   *) false ;;
>   esac
> 
> perhaps.

Good point.

Merijn, please be sure to squash this fix in before you submit the final
thing.

Thanks,
Johannes

> 
> > +test_expect_success !DOT_IN_PATH 'run_command is restricted to PATH' '
> > write_script should-not-run <<-\EOF &&
> > echo yikes
> > EOF
> > -- snap --
> >
> > If so, can you please provide a commit message for it (you can add my
> > Signed-off-by: line and your Tested-by: line).
> >
> > Thanks,
> > Johannes
> 


Re: [PATCH 2/2] format-patch: allow for independent diff & range-diff options

2018-11-29 Thread Johannes Schindelin
Hi Ævar,

On Wed, 28 Nov 2018, Ævar Arnfjörð Bjarmason wrote:

> Change the semantics of the "--range-diff" option so that the regular
> diff options can be provided separately for the range-diff and the
> patch. This allows for supplying e.g. --range-diff-U0 and -U1 to
> "format-patch" to provide different context for the range-diff and the
> patch. This wasn't possible before.

I really, really dislike the `--range-diff-`. We have
precedent for passing optional arguments that are passed to some other
command, so a much more logical and consistent convention would be to use
`--range-diff[=..]`, allowing all of the diff options that
you might want to pass to the outer diff in one go rather than having a
lengthy string of `--range-diff-this` and `--range-diff-that` options.

I only had time to skim the patch, and I have to wonder why you pass
around full-blown `rev_info` structs for range diff (and with that really
awful name `rd_rev`) rather than just the `diff_options` that you
*actually* care about?

Ciao,
Dscho

> 
> Ever since the "--range-diff" option was added in
> 31e2617a5f ("format-patch: add --range-diff option to embed diff in
> cover letter", 2018-07-22) the "rev->diffopt" we pass down to the diff
> machinery has been the one we get from "format-patch"'s own
> setup_revisions().
> 
> This sort of thing is unique among the log-like commands in
> builtin/log.c, no command than format-patch will embed the output of
> another log-like command. Since the "rev->diffopt" is reused we need
> to munge it before we pass it to show_range_diff(). See
> 43dafc4172 ("format-patch: don't include --stat with --range-diff
> output", 2018-11-22) for a related regression fix which is being
> mostly reverted here.
> 
> Implementation notes: 1) We're not bothering with the full teardown
> around die() and will leak memory, but it's too much boilerplate to do
> all the frees with/without the die() and not worth it. 2) We call
> repo_init_revisions() for "rd_rev" even though we could get away with
> a shallow copy like the code we're replacing (and which
> show_range_diff() itself does). This is to make this code more easily
> understood.
> 
> Signed-off-by: Ævar Arnfjörð Bjarmason 
> ---
>  Documentation/git-format-patch.txt | 10 ++-
>  builtin/log.c  | 42 +++---
>  t/t3206-range-diff.sh  | 41 +
>  3 files changed, 82 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/git-format-patch.txt 
> b/Documentation/git-format-patch.txt
> index aba4c5febe..6c048f415f 100644
> --- a/Documentation/git-format-patch.txt
> +++ b/Documentation/git-format-patch.txt
> @@ -24,7 +24,8 @@ SYNOPSIS
>  [--to=] [--cc=]
>  [--[no-]cover-letter] [--quiet] [--notes[=]]
>  [--interdiff=]
> -[--range-diff= [--creation-factor=]]
> +[--range-diff= [--creation-factor=]
> +   [--range-diff]]
>  [--progress]
>  []
>  [  |  ]
> @@ -257,6 +258,13 @@ feeding the result to `git send-email`.
>   creation/deletion cost fudge factor. See linkgit:git-range-diff[1])
>   for details.
>  
> +--range-diff::
> + Other options prefixed with `--range-diff` are stripped of
> + that prefix and passed as-is to the diff machinery used to
> + generate the range-diff, e.g. `--range-diff-U0` and
> + `--range-diff--no-color`. This allows for adjusting the format
> + of the range-diff independently from the patch itself.
> +
>  --notes[=]::
>   Append the notes (see linkgit:git-notes[1]) for the commit
>   after the three-dash line.
> diff --git a/builtin/log.c b/builtin/log.c
> index 02d88fa233..7658e56ecc 100644
> --- a/builtin/log.c
> +++ b/builtin/log.c
> @@ -1023,7 +1023,8 @@ static void show_diffstat(struct rev_info *rev,
>   fprintf(rev->diffopt.file, "\n");
>  }
>  
> -static void make_cover_letter(struct rev_info *rev, int use_stdout,
> +static void make_cover_letter(struct rev_info *rev, struct rev_info *rd_rev,
> +   int use_stdout,
> struct commit *origin,
> int nr, struct commit **list,
> const char *branch_name,
> @@ -1095,13 +1096,9 @@ static void make_cover_letter(struct rev_info *rev, 
> int use_stdout,
>   }
>  
>   if (rev->rdiff1) {
> - struct diff_options opts;
> - memcpy(, >diffopt, sizeof(opts));
> - opts.output_format &= ~(DIFF_FORMAT_DIFFSTAT | 
> DIFF_FORMAT_SUMMARY);
> -
>   fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title);
>   show_range_diff(rev->rdiff1, rev->rdiff2,
> - rev->creation_factor, 1, );
> + rev->creation_factor, 1, _rev->diffopt);
>   }
>  }
>  
> @@ -1485,6 +1482,7 @@ int cmd_format_patch(int argc, const char 

Re: [PATCH] pack-protocol.txt: accept error packets in any context

2018-11-29 Thread Junio C Hamano
Masaya Suzuki  writes:

> In the Git pack protocol definition, an error packet may appear only in
> a certain context. However, servers can face a runtime error (e.g. I/O
> error) at an arbitrary timing. This patch changes the protocol to allow
> an error packet to be sent instead of any packet.
>
> Following this protocol spec change, the error packet handling code is
> moved to pkt-line.c.
>
> Signed-off-by: Masaya Suzuki 
> ---

Have you run tests with this applied?  I noticed 5703.9 now has
stale expectations, but there may be others.


Re: [PATCH] rebase -i: introduce the 'test' command

2018-11-29 Thread Johannes Schindelin
Hi Paul,

On Wed, 28 Nov 2018, Paul Morelle wrote:

> On 28/11/18 16:19, Johannes Schindelin wrote:
> >
> > On Wed, 28 Nov 2018, Paul Morelle wrote:
> >
> >> The 'exec' command can be used to run tests on a set of commits,
> >> interrupting on failing commits to let the user fix the tests.
> >>
> >> However, the 'exec' line has been consumed, so it won't be ran again by
> >> 'git rebase --continue' is ran, even if the tests weren't fixed.
> >>
> >> This commit introduces a new command 'test' equivalent to 'exec', except
> >> that it is automatically rescheduled in the todo list if it fails.
> >>
> >> Signed-off-by: Paul Morelle 
> > Would it not make more sense to add a command-line option (and a config
> > setting) to re-schedule failed `exec` commands? Like so:
> 
> Your proposition would do in most cases, however it is not possible to
> make a distinction between reschedulable and non-reschedulable commands.

True. But I don't think that's so terrible.

What I think is something to avoid is two commands that do something very,
very similar, but with two very, very different names.

In reality, I think that it would even make sense to change the default to
reschedule failed `exec` commands. Which is why I suggested to also add a
config option.

> Do you think that we can ignore the distinction between reschedulable
> and non-reschedulable commands in the same script?

Yes, I think that there *should not* be any distinction. It would just
make it harder to use the feature (users would have to keep in mind that
one version reschedules, one version does not).

> In this case, I would add some tests to your patch below, and propose
> the result on this mailing list.

I already added a test... See the reschedule-failed-exec branch on
https://github.com/dscho/git.

And I had another idea. To make this feature more useful for *myself*, I
would like to introduce the `-X` option as a shortcut for
`--reschedule-failed-exec -x`, e.g.

git rebase -X "make -j15 test" 

What do you think?
Johannes

> 
> > -- snip --
> > diff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c
> > index a2ab68ed0632..a9ab009fdbca 100644
> > --- a/builtin/rebase--interactive.c
> > +++ b/builtin/rebase--interactive.c
> > @@ -192,6 +192,8 @@ int cmd_rebase__interactive(int argc, const char 
> > **argv, const char *prefix)
> > OPT_STRING(0, "onto-name", _name, N_("onto-name"), 
> > N_("onto name")),
> > OPT_STRING(0, "cmd", , N_("cmd"), N_("the command to run")),
> > OPT_RERERE_AUTOUPDATE(_rerere_auto),
> > +   OPT_BOOL(0, "reschedule-failed-exec", 
> > _failed_exec,
> > +N_("automatically re-schedule any `exec` that fails")),
> > OPT_END()
> > };
> >  
> > diff --git a/builtin/rebase.c b/builtin/rebase.c
> > index 5b3e5baec8a0..700cbc4e150e 100644
> > --- a/builtin/rebase.c
> > +++ b/builtin/rebase.c
> > @@ -104,6 +104,7 @@ struct rebase_options {
> > int rebase_merges, rebase_cousins;
> > char *strategy, *strategy_opts;
> > struct strbuf git_format_patch_opt;
> > +   int reschedule_failed_exec;
> >  };
> >  
> >  static int is_interactive(struct rebase_options *opts)
> > @@ -415,6 +416,8 @@ static int run_specific_rebase(struct rebase_options 
> > *opts)
> > argv_array_push(, opts->gpg_sign_opt);
> > if (opts->signoff)
> > argv_array_push(, "--signoff");
> > +   if (opts->reschedule_failed_exec)
> > +   argv_array_push(, 
> > "--reschedule-failed-exec");
> >  
> > status = run_command();
> > goto finished_rebase;
> > @@ -903,6 +906,9 @@ int cmd_rebase(int argc, const char **argv, const char 
> > *prefix)
> >"strategy")),
> > OPT_BOOL(0, "root", ,
> >  N_("rebase all reachable commits up to the root(s)")),
> > +   OPT_BOOL(0, "reschedule-failed-exec",
> > +_failed_exec,
> > +N_("automatically re-schedule any `exec` that fails")),
> > OPT_END(),
> > };
> > int i;
> > @@ -1195,6 +1201,9 @@ int cmd_rebase(int argc, const char **argv, const 
> > char *prefix)
> > break;
> > }
> >  
> > +   if (options.reschedule_failed_exec && !is_interactive())
> > +   die(_("--reschedule-failed-exec requires an interactive 
> > rebase"));
> > +
> > if (options.git_am_opts.argc) {
> > /* all am options except -q are compatible only with --am */
> > for (i = options.git_am_opts.argc - 1; i >= 0; i--)
> > diff --git a/sequencer.c b/sequencer.c
> > index e1a4dd15f1a8..69bee63e116f 100644
> > --- a/sequencer.c
> > +++ b/sequencer.c
> > @@ -158,6 +158,7 @@ static GIT_PATH_FUNC(rebase_path_strategy, 
> > "rebase-merge/strategy")
> >  static GIT_PATH_FUNC(rebase_path_strategy_opts, 
> > "rebase-merge/strategy_opts")
> >  static