How do I modify the commit message (not the topmost one) of a git commit?

2013-05-04 Thread Norah Jones
Hi, 

I did a series of commits and now I find one of my commit (not the topmost one) 
has an incorrect commit message. How can I change that specific one? I believe 
git commit --amend works only for the last commit.


Thanks,
Norah Jones


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Pitfalls in auto-fast-forwarding heads that are not checked out?

2013-05-04 Thread Johannes Sixt
Am 04.05.2013 00:46, schrieb Martin Langhoff:
 I am building a small git wrapper around puppet, and one of the
 actions it performs is auto-fastforwarding of branches without
 checking them out.
 
 In simplified code... we ensure that we are on a head called master,
 and in some cases ppg commit, will commit to master and...
 
   ## early on
   # sanity-check we are on master
   headname=$(git rev-parse --symbolic-full-name --revs-only HEAD)
   if [ $headname -ne refs/heads/headname ]; then

You mean refs/heads/master and != here because -ne is numeric
comparison in a shell script.

   echo 2 ERROR: can only issue --immediate commit from the
 master branch!
   exit 1
   fi
 
   ## then
   git commit -bla blarg baz
 
   ## and then...
 
   # ensure we can ff
   head_sha1=$(git rev-parse --revs-only master)
   mb=$(git merge-base $production_sha1 refs/heads/master)
   if [[ $mb -ne $production_sha1 ]]; then

Your approach looks OK (but note again the incorrect -ne).

Since git 1.8.0 you can express this check as

if git merge-base --is-ancestor $production_sha1 refs/heads/master

   echo 2 ERROR: cannot fast-forward master to production

echo 2 ERROR: cannot fast-forward production to master

   exit 1
   fi
   $GIT_EXEC_PATH/git-update-ref -m ppg immediate commit
 refs/heads/production $head_sha1 $production_sha1 || exit 1
 
 Are there major pitfalls in this approach?

I don't think there are.

 I cannot think of any, but
 git has stayed away from updating my local tracking branches; so maybe
 there's a reason for that...

I don't understand what you are saying here. What is that?

-- Hannes

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Add porcelain command to revert a single staged file to its HEAD state while preserving its staged state

2013-05-04 Thread Dimitar Bonev
Hi,

I have been looking for such a command/option and no one gave me
sufficient answer. So this message should be considered as a feature
request. I had a situation where I had staged a file with a problem
solution in it, then I wanted to experiment with a different solution
so I had to revert the file to its HEAD state and I couldn't find a
way that preserves the staged state of that file. More discussions:

https://groups.google.com/forum/?fromgroups=#!topic/git-users/nYiN-rE_3i0

http://stackoverflow.com/questions/16335799/git-porcelain-command-to-revert-a-single-file-to-its-head-state-but-keep-its-sta

Regards,
Dimitar Bonev
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: How do I modify the commit message (not the topmost one) of a git commit?

2013-05-04 Thread Johan Herland
On Sat, May 4, 2013 at 8:31 AM, Norah Jones nh.jone...@gmail.com wrote:
 Hi,

 I did a series of commits and now I find one of my commit (not the topmost 
 one) has an incorrect commit message. How can I change that specific one? I 
 believe git commit --amend works only for the last commit.

True. Be aware that git commit --amend and the rebasing shown below
amounts to rewriting history, which is fine when it's your own local
history, but if you've already shared the commits you are changing,
then you're forcing your collaborators to rebase their own work on top
of your rewritten history.

That said, here's how to do a rebase to change a specific commit message:

0. Make sure you have a clean worktree. git stash any uncommitted changes.

1. Identify the commit you want to change, e.g. by using something
like HEAD~5 (for the 5th last commit on your current branch), or by
the 40-character commit id.

2. git rebase -i $commit^, where $commit is the commit you
identified above, and the trailing caret ^ is important. (rebase
works on a range of commits, and you want to start the rebase based on
the parent of the commit you wish to change).

3. The rebase command will open your text editor with a list of your
commits, from the one you'd like to change, to your most recent
commit. Each commit is prefixed with the word pick, which indicates
that rebase will replay that commit without any changes. You want to
change the commit message for the first commit in this list, so on the
first line, change the pick into reword. Save and exit the editor.

4. Rebase will now start replaying the commits from your list. The
first thing that will happen, is that it will reopen your text editor
with the commit message for the commit you want to change. Edit the
commit message to your liking, and save and exit the editor.

5. Rebase will then replay all the following commits until the last
commit is done, and you're back where you were when you started the
rebase. Since you did nothing more than change a commit message, you
will not get any conflicts during the rebase.

6. If you stashed some uncommitted changes in step #0, you might want
to un-stash them now: git stash pop


Hope this helps,

...Johan

-- 
Johan Herland, jo...@herland.net
www.herland.net
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/5] t1508 (at-combinations): more tests; document failures

2013-05-04 Thread David Aguilar
On Thu, May 2, 2013 at 10:09 AM, Ramkumar Ramachandra
artag...@gmail.com wrote:
 Felipe Contreras wrote:
 We probably should fix those, but that is orthogonal to the '@' shortcut.

 We can have the '@' shortcut *today*, with minimal changes to the code
 and the documentation, in a limited and understood scope, with no
 surprises.

 We can fix the symbolic ref stuff slowly, step by step, no need to
 delay the '@' shortcut for that.

 Agreed.

If only we didn't care about windows then we could have this feature today:

cd .git
ln -s HEAD @

...and everything works, in the most natural way.
Has anyone else tweaked their repo this way?

Is an alternative implementation to change the template repo to ship
with a symlink?

For windows, perhaps we can use this new code behind an #ifdef?

Anyways, it's just a crazy idea.  I very much like this feature,
and in a tweaked repo @{0}{1} actually works.

Is there no way to tweak this at some really low level to trick git
into believing the link exists (even when it doesn't)?

I guess that's what these patches do, but the limitations seem unfortunate.
--
David
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/5] t1508 (at-combinations): more tests; document failures

2013-05-04 Thread David Aguilar
On Sat, May 4, 2013 at 1:10 AM, David Aguilar dav...@gmail.com wrote:
 On Thu, May 2, 2013 at 10:09 AM, Ramkumar Ramachandra
 artag...@gmail.com wrote:
 Felipe Contreras wrote:
 We probably should fix those, but that is orthogonal to the '@' shortcut.

 We can have the '@' shortcut *today*, with minimal changes to the code
 and the documentation, in a limited and understood scope, with no
 surprises.

 We can fix the symbolic ref stuff slowly, step by step, no need to
 delay the '@' shortcut for that.

 Agreed.

 If only we didn't care about windows then we could have this feature today:

 cd .git
 ln -s HEAD @

 ...and everything works, in the most natural way.
 Has anyone else tweaked their repo this way?

 Is an alternative implementation to change the template repo to ship
 with a symlink?

 For windows, perhaps we can use this new code behind an #ifdef?

 Anyways, it's just a crazy idea.  I very much like this feature,
 and in a tweaked repo @{0}{1} actually works.

 Is there no way to tweak this at some really low level to trick git
 into believing the link exists (even when it doesn't)?

 I guess that's what these patches do, but the limitations seem unfortunate.

Nevermind.  @{0}{1} is nothing special and symbolic-ref happily
replaces symlinks with a file, so new code is needed regardless.  I'll
start testing these patches instead.
--
David
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/2] remote-bzr: avoid bad refs

2013-05-04 Thread Stefano Lattarini
On 05/04/2013 02:31 AM, Felipe Contreras wrote:
 Turns out fast-export throws bad 'reset' commands because of a behavior
 in transport-helper that is not even needed.
 
 We should ignore them, otherwise we will threat

s/threat/treat/

 them as branches and fail.
 
 This was fixed in v1.8.2, but some people use this script in older
 versions of git.
 
 Also, check if the ref was a tag, and skip it for now.

Regards,
  Stefano
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: What's cooking in git.git (Apr 2013, #10; Mon, 29)

2013-05-04 Thread Thomas Rast
Junio C Hamano gits...@pobox.com writes:

 * jn/config-ignore-inaccessible (2013-04-15) 1 commit
  - config: allow inaccessible configuration under $HOME

  When $HOME is misconfigured to point at an unreadable directory, we
  used to complain and die. This loosens the check.

  I do not think we agreed that this is a good idea, though.

As a data point: yesterday on IRC, two users complained that they each
had this problem.

  http://colabti.org/irclogger/irclogger_log/git?date=2013-05-03#l3022
  http://colabti.org/irclogger/irclogger_log/git?date=2013-05-03#l3111

So for one thing, ha ha we told you so is not an extremely
satisfactory answer, especially since we only told them so with the
recent doc update.  Wouldn't a stern warning or even an early error be
better?  It could be tempered by checking that HOME agrees with what
getpwnam says should be the HOME of the existing user, and checking that
it is not readable, before warning; more experienced users like the
scenario you mention in

  http://thread.gmane.org/gmane.comp.version-control.git/220661/focus=220921

would make sure that at least one of those conditions is not true.

But for another, they both claim that it fails even with HOME unset(!)
and even with a completely empty environment.  I cannot reproduce this,
but there might be another issue lurking?

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Add porcelain command to revert a single staged file to its HEAD state while preserving its staged state

2013-05-04 Thread Thomas Rast
Dimitar Bonev dsbo...@gmail.com writes:

 I have been looking for such a command/option and no one gave me
 sufficient answer. So this message should be considered as a feature
 request. I had a situation where I had staged a file with a problem
 solution in it, then I wanted to experiment with a different solution
 so I had to revert the file to its HEAD state and I couldn't find a
 way that preserves the staged state of that file. More discussions:

 https://groups.google.com/forum/?fromgroups=#!topic/git-users/nYiN-rE_3i0

 http://stackoverflow.com/questions/16335799/git-porcelain-command-to-revert-a-single-file-to-its-head-state-but-keep-its-sta

Is that a common enough issue to warrant a better solution than

  git show HEAD:targetfile  targetfile

which is how we would do it?

Or more likely,

  git commit -m WIP
  git revert -n HEAD

which is safer anyway, since it doesn't lose the formerly-staged state
so easily (you have the reflog in case of any mistakes).

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Add porcelain command to revert a single staged file to its HEAD state while preserving its staged state

2013-05-04 Thread Dimitar Bonev
I think if there was such a command, it could well be common, at least
for me. I am somewhat surprised that  from the three combinations of
resetting index and working dir's states of a file this is the one
that is missing (it is missing at commit level also for what is
worth). Summary table of resetting commands is present at the end of
this article: http://www.progit.org/blog/2011/07/11/reset.html

Here is how I see the workflow for a file: you start with a state that
matches the HEAD state, you modify the file until reaching the point
of a sufficient solution, you mark it as finished work by staging it
for the next commit, now that you have a solution you can start over
from the HEAD state of the file and try to improve it by choosing a
different path of implementation.

My initial thought was to checkout the file, but surprisingly this
reset the staged state also in addition the working dir's state.
Generally git-checkout modifies the working tree, but indeed if you
use its form for a single file and specify a treeish argument it will
update the index for the given paths before updating the working
tree. I am curious which are the valid use cases for this behavior of
git-checkout and if it was the right thing to do to implement it this
way. In its current form git-checkout does more work than expected by
me:

git checkout HEAD -- targetfile

The above command should have been implemented to reset the working
dir' state of the file only and if one wants to reset its staged state
he could use 'git reset HEAD targetfile'. This gives you more
flexibility (reset one state, the other state or both states),
git-checkout has more consistent behavior (git-checkout a file and
git-checkout a branch keeps your staged changes), and makes harder to
lose your staged changes (there is a reason for a change to be staged
so it should not be so easy to lose it). As the current behavior is
released I guess it couldn't not be (or it should not be at all)
accommodated to the one described above, so at least another
command/option should be added to implement it.

@ThomasRast: 'git show HEAD:targetfile  targetfile' was proposed in
the both links that I provided in the email that your replied to, but
this introduces external dependency to the command interpreter to
output the file unmodified but not every interpreter does this.
PowerShell in particular modifies the encoding of the file, so I get
strange behavior: 'git diff' states that html files are binary ones
and it does not show me the differences; 'git apply' prints 'fatal:
unrecognized input'. I tried your second suggestion 'git commit'
followed by 'git revert', but this reverses the states of all
committed files. I prefer something that applies to a single file,
like git-checkout and git-reset do. Here is a set of commands more
close to what I wish:

git commit -m 'a provisional stable solution'
git checkout HEAD~1 -- targetfile
git commit  --amend -am 'add solution to problem x'

This requires more commands, makes assumptions about making a commit
to a branch, deviates from the rest of git commands about resetting a
file's state (inconsistent git API).

On Sat, May 4, 2013 at 11:58 AM, Thomas Rast tr...@inf.ethz.ch wrote:
 Dimitar Bonev dsbo...@gmail.com writes:

 I have been looking for such a command/option and no one gave me
 sufficient answer. So this message should be considered as a feature
 request. I had a situation where I had staged a file with a problem
 solution in it, then I wanted to experiment with a different solution
 so I had to revert the file to its HEAD state and I couldn't find a
 way that preserves the staged state of that file. More discussions:

 https://groups.google.com/forum/?fromgroups=#!topic/git-users/nYiN-rE_3i0

 http://stackoverflow.com/questions/16335799/git-porcelain-command-to-revert-a-single-file-to-its-head-state-but-keep-its-sta

 Is that a common enough issue to warrant a better solution than

   git show HEAD:targetfile  targetfile

 which is how we would do it?

 Or more likely,

   git commit -m WIP
   git revert -n HEAD

 which is safer anyway, since it doesn't lose the formerly-staged state
 so easily (you have the reflog in case of any mistakes).

 --
 Thomas Rast
 trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Pitfalls in auto-fast-forwarding heads that are not checked out?

2013-05-04 Thread Martin Langhoff
On Sat, May 4, 2013 at 3:34 AM, Johannes Sixt j...@kdbg.org wrote:
 You mean refs/heads/master and != here because -ne is numeric
 comparison in a shell script.

thanks! Yeah, I fixed those up late last night :-)

 Since git 1.8.0 you can express this check as

 if git merge-base --is-ancestor $production_sha1 refs/heads/master

Ah, that's great! Unfortunate it's not there in earlier / more widely
used releases of git.

 Are there major pitfalls in this approach?

 I don't think there are.

Thanks...

 I cannot think of any, but
 git has stayed away from updating my local tracking branches; so maybe
 there's a reason for that...

 I don't understand what you are saying here. What is that?

When I do git pull, git is careful to only update the branch I have
checked out (if appropriate). It leaves any other branches that track
branches on the remote that has just been fetched untouched. I always
thought that at some point git pull would learn to evaluate those
branches and auto-merge them if the merge is a ff.

I would find that a natural bit of automation in git pull. Of course
it would mean a change of semantics, existing scripts could be
affected.

cheers,



m
--
 martin.langh...@gmail.com
 -  ask interesting questions
 - don't get distracted with shiny stuff  - working code first
 ~ http://docs.moodle.org/en/User:Martin_Langhoff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Another use of @?

2013-05-04 Thread Ramkumar Ramachandra
[joining the discussion late; was travelling]

Duy Nguyen wrote:
 git co long-branch-name
 git diff A/@
 git reset --hard A/@

In this form, this looks highly inconsistent.  You have to decide if
you want @ to resolve to the current branch name or HEAD.  Our current
@-proposal makes @@{1} display the reflog for HEAD for instance.  The
other problem is that we resolve things like @{-1} to full refs like
refs/heads/master.  Making a A/@{-1} work makes little or no sense,
because that refs/heads needs to be changed to refs/remotes in the
first place.  What about refs/decapitated/@{-1}?  Should we support
it?

I tend to agree with Junio here: @{u} is the way forward.  We need to
define useful reduced consistent semantics; while inventing a
mini-language to do all kinds of revision manipulations may be a fun
theoretical exercise, it's too much effort for too little gain.  We
have to learn to work within the limitations of what we've invented so
far.

On Matthieu's note, I have a comment: symbolic refs are an absolute
dead end.  We didn't think of it from the start, and it's too late
now.  Do NOT go there: from my investigation, I believe that hooking
up everything to the revision parser is the way forward.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Pitfalls in auto-fast-forwarding heads that are not checked out?

2013-05-04 Thread John Szakmeister
On Sat, May 4, 2013 at 7:35 AM, Martin Langhoff
martin.langh...@gmail.com wrote:
[snip]
 When I do git pull, git is careful to only update the branch I have
 checked out (if appropriate). It leaves any other branches that track
 branches on the remote that has just been fetched untouched. I always
 thought that at some point git pull would learn to evaluate those
 branches and auto-merge them if the merge is a ff.

 I would find that a natural bit of automation in git pull. Of course
 it would mean a change of semantics, existing scripts could be
 affected.

I agree.  I've been using this script for quite a while now:

https://github.com/jszakmeister/etc/blob/master/git-addons/git-ffwd

I've been pretty happy with it.  It's not of my own design, I picked
up from StackOverflow:

http://stackoverflow.com/a/9076361/683080

And made a couple of minor tweaks to cope with my configuration (I
have merge setup to not fast-forward merge by default).

-John
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] revision.c: Fix a sparse warning

2013-05-04 Thread Ramsay Jones

Sparse issues an 'sole_interesting' not declared. Should it be static?
warning. In order to suppress the warning, since this symbol does not
need more than file visibility, we simply add the static modifier to
its declaration.

Signed-off-by: Ramsay Jones ram...@ramsay1.demon.co.uk
---

Hi Kevin,

If you need to re-roll your 'kb/full-history-compute-treesame-carefully'
branch, could you please squash this into commit 039bdad1 (revision.c:
discount UNINTERESTING parents, 30-04-2013).

Thanks!

ATB,
Ramsay Jones

 revision.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/revision.c b/revision.c
index dd48c55..60c8d8c 100644
--- a/revision.c
+++ b/revision.c
@@ -349,7 +349,7 @@ static int everybody_uninteresting(struct commit_list *orig)
  * (and multiple UNINTERESTING ones), then we can't choose a parent to follow,
  * and we should not be simplified.
  */
-struct commit *sole_interesting(struct rev_info *revs, struct commit_list 
*orig)
+static struct commit *sole_interesting(struct rev_info *revs, struct 
commit_list *orig)
 {
struct commit_list *list = orig;
struct commit *interesting = NULL;
-- 
1.8.2

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] revision.c: Fix a sparse warning

2013-05-04 Thread Kevin Bracey

On 04/05/2013 20:25, Ramsay Jones wrote:

Sparse issues an 'sole_interesting' not declared. Should it be static?
warning. In order to suppress the warning, since this symbol does not
need more than file visibility, we simply add the static modifier to
its declaration.



Thanks! I'll include that fix.

Kevin

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Add porcelain command to revert a single staged file to its HEAD state while preserving its staged state

2013-05-04 Thread Jonathan Nieder
Dimitar Bonev wrote:

 @ThomasRast: 'git show HEAD:targetfile  targetfile' was proposed in
 the both links that I provided in the email that your replied to, but
 this introduces external dependency to the command interpreter to
 output the file unmodified but not every interpreter does this.
 PowerShell in particular modifies the encoding of the file

That would suggest that git show (along with similar commands like
git diff) should learn an --output= option to avoid its output being
corrupted.  It doesn't leave me very happy.

Is there no way to convince PowerShell to treat the output of a
command as binary data with no particular encoding?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Pitfalls in auto-fast-forwarding heads that are not checked out?

2013-05-04 Thread Jonathan Nieder
Martin Langhoff wrote:
 On Sat, May 4, 2013 at 3:34 AM, Johannes Sixt j...@kdbg.org wrote:

 Since git 1.8.0 you can express this check as

 if git merge-base --is-ancestor $production_sha1 refs/heads/master

 Ah, that's great! Unfortunate it's not there in earlier / more widely
 used releases of git.

Another trick is to use git push:

git push . $production_sha1:refs/heads/master

This advances the master branch if

 (1) it is not the current branch, and
 (2) that update is a fast-forward

It can be convenient sometimes.

Hope that helps,
Jonathan
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/4] fast-export: don't parse all the commits

2013-05-04 Thread Junio C Hamano
Felipe Contreras felipe.contre...@gmail.com writes:

 This updates the parse_object() moved by the previous patch. At this
 point in the codeflow, unlike the original, we already _know_ the
 object must be a commit; wouldn't an equivalent of:

 object = (lookup_commit(sha1)-object)

 be more correct here?

 Maybe, if we want to run some extra code we don't care about.

 The only actual difference is that object-type will be OBJ_COMMIT,
 ...

The reason to prefer lookup_commit() over lookup_unknown_object() is
primarily that we allocate the storage for known type, not union,
out of the allocation pool (alloc.c) for the known type.  Also we
mark the result with the type so that we can catch mistakes in data
when later code somehow expects an object with the same object name
to be of different type; while the latter is a good safety measure,
I do not think it matters that much in this codepath. The former is
more important in general.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: What's cooking in git.git (Apr 2013, #10; Mon, 29)

2013-05-04 Thread Junio C Hamano
Thomas Rast tr...@inf.ethz.ch writes:

 So for one thing, ha ha we told you so is not an extremely
 satisfactory answer, especially since we only told them so with the
 recent doc update.  Wouldn't a stern warning or even an early error be
 better?  

Sorry, I am not sure exactly what alternative you have in mind here
by a stern warning / an early error.

 It could be tempered by checking that HOME agrees with what
 getpwnam says should be the HOME of the existing user, and checking that
 it is not readable, before warning; more experienced users like the
 scenario you mention in

   http://thread.gmane.org/gmane.comp.version-control.git/220661/focus=220921

 would make sure that at least one of those conditions is not true.

Perhaps.

An update to change the rule easier to explain and the messages
easier to understand to help inexperienced users in the right
direction would be good.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Add porcelain command to revert a single staged file to its HEAD state while preserving its staged state

2013-05-04 Thread Junio C Hamano
Thomas Rast tr...@inf.ethz.ch writes:

 I have been looking for such a command/option and no one gave me
 sufficient answer. So this message should be considered as a feature
 request. I had a situation where I had staged a file with a problem
 solution in it, then I wanted to experiment with a different solution
 so I had to revert the file to its HEAD state and I couldn't find a
 way that preserves the staged state of that file.
 ...

I have something worth saving, better than HEAD in some way
(e.g. contains fixes), in my index. I want to keep it while I
experiment an approach that is unrelated to it, so I want a clean
slate in the working tree from HEAD without disturbing the index.

At the first glance, that looks like a reasonable thing to ask, but
after thinking about it a bit more, I am not sure if it really is,
primarily because it is unclear what you can productively do to the
end result next.

Suppose you matched the working tree to HEAD while keeping a
valuable change in the index, and after working for a while, now
have finished the experiment and have something in your working
tree.

What is your next move?

If the end result in the working tree were Nah, this other approach
does not work, trash it, you can checkout the working tree from the
index, so nothing is lost.

But if your result is _also_ something worth saving, what would you
do?  git add to update the index will trash the work that was in
the index, and that is by definition unrelated to what you worked on
in the working tree (you wanted to start from the version in the
HEAD, not from the version in the index, so the end result is likely
to lack the work you saved in the index).

That makes me think that match working tree from HEAD bypassing
index is not a very useful strategy, unless you are expecting a
failed experiment from the start.

As Thomas said, I think a more reasonable workflow would begin by
saving the somewhat worth saving state you have in your index as a
WIP commit, i.e.

git commit -m wip

When I experiment starting from a clean slate (after saving away
such a WIP commit), I would then do this:

git checkout HEAD^

to start at the state before the WIP commit and hack away.  As I do
not know how the experiment would go when I do this, I often do not
bother giving the experiment its own branch.

If the experiment does not seem to go in a productive direction, I
can simply git reset --hard  git checkout - to get rid of it.

On the other hand, if its direction shows promise but turns out to
be more involved than a quick hack, I can at that point decide to
give it its own branch with git checkout -b newbranch.  Then I can
choose to keep working on it, or switch to other tasks after making
a wip commit on that new branch.

Or if the experiment results in a series of good and straightforward
changes that should come _before_ that original wip (which happens
very often), then I could do:

git commit ;# maybe more commits.
git cherry-pick @{-1} ;# the one stashed away
git co -B @{-1}

to update the original branch and come back to it.  The state in the
original index may be a WIP, so I may then reset with

git reset HEAD^

after the above.

 Is that a common enough issue to warrant a better solution than

   git show HEAD:targetfile  targetfile

 which is how we would do it?

Or git diff HEAD paths | git apply -R, which is a good trick to
learn.  You can inspect git diff HEAD paths to check what you
will lose and then add | git apply -R to actually revert it.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Add porcelain command to revert a single staged file to its HEAD state while preserving its staged state

2013-05-04 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 I have something worth saving, better than HEAD in some way
 (e.g. contains fixes), in my index. I want to keep it while I
 experiment an approach that is unrelated to it, so I want a clean
 slate in the working tree from HEAD without disturbing the index.

 At the first glance, that looks like a reasonable thing to ask, but
 after thinking about it a bit more, I am not sure if it really is,
 primarily because it is unclear what you can productively do to the
 end result next.

 Suppose you matched the working tree to HEAD while keeping a
 valuable change in the index, and after working for a while, now
 have finished the experiment and have something in your working
 tree.

 What is your next move?

 If the end result in the working tree were Nah, this other approach
 does not work, trash it, you can checkout the working tree from the
 index, so nothing is lost.

 But if your result is _also_ something worth saving, what would you
 do?  git add to update the index will trash the work that was in
 the index, and that is by definition unrelated to what you worked on
 in the working tree (you wanted to start from the version in the
 HEAD, not from the version in the index, so the end result is likely
 to lack the work you saved in the index).

 That makes me think that match working tree from HEAD bypassing
 index is not a very useful strategy, unless you are expecting a
 failed experiment from the start.

 As Thomas said, I think a more reasonable workflow would begin by
 saving the somewhat worth saving state you have in your index as a
 WIP commit, i.e.

   git commit -m wip

 When I experiment starting from a clean slate (after saving away
 such a WIP commit), I would then do this:

 git checkout HEAD^

 to start at the state before the WIP commit and hack away.  As I do
 not know how the experiment would go when I do this, I often do not
 bother giving the experiment its own branch.

 If the experiment does not seem to go in a productive direction, I
 can simply git reset --hard  git checkout - to get rid of it.

 On the other hand, if its direction shows promise but turns out to
 be more involved than a quick hack, I can at that point decide to
 give it its own branch with git checkout -b newbranch.  Then I can
 choose to keep working on it, or switch to other tasks after making
 a wip commit on that new branch.

 Or if the experiment results in a series of good and straightforward
 changes that should come _before_ that original wip (which happens
 very often), then I could do:

   git commit ;# maybe more commits.
   git cherry-pick @{-1} ;# the one stashed away
   git co -B @{-1}

 to update the original branch and come back to it.

Also, if the alternative experiment was really to replace what you
originally did to your index, as a natural extension to the above
workflow, you would omit cherry-pick step in the above.  Your
perfected alternative solution will become the true history of the
original branch, discarding the tentative solution in the index.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


jn/config-ignore-inaccessible (Re: What's cooking in git.git (Apr 2013, #10; Mon, 29))

2013-05-04 Thread Jonathan Nieder
Thomas Rast wrote:
 Junio C Hamano gits...@pobox.com writes:

 * jn/config-ignore-inaccessible (2013-04-15) 1 commit
  - config: allow inaccessible configuration under $HOME

  When $HOME is misconfigured to point at an unreadable directory, we
  used to complain and die. This loosens the check.

  I do not think we agreed that this is a good idea, though.

 As a data point: yesterday on IRC, two users complained that they each
 had this problem.

   http://colabti.org/irclogger/irclogger_log/git?date=2013-05-03#l3022
   http://colabti.org/irclogger/irclogger_log/git?date=2013-05-03#l3111

I think the approach taken in the patch above is a good one.  If
/etc/gitconfig contains important configuration, it is still not
ignored, errors other than permissions reading ~/.gitconfig are
still fatal, and permissions errors accessing ~/.gitconfig are no
longer fatal because they are expected as something very common
in normal setups.

I haven't been able to convince myself there is a different, better
behavior to be found.  Special-casing inaccessible $HOME while still
forbidding inaccessible $HOME/.config/git and $HOME/.gitconfig would
seem strange.

Hmm?
Jonathan
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 8/8] revision.c: discount UNINTERESTING parents

2013-05-04 Thread Kevin Bracey
On 02/05/2013 23:05, Junio C Hamano wrote:

   Z...A===X---o---o---B
\\/
 W---Y

 OK, I think I understand it, and we are in agreement.  For the
 purpose of the above paragraph, a side branch is what is not on the
 --ancestry-path, so all of the below examples are about the
 behaviour when --ancestry-path is used.

Ah, in fact, no. In some previous mails I was concentrating on
ancestry-path, but those 3 examples were really of ordinary A..B, with
W+Y in the INTERESTING set. I think the side-branch logic remains sound
and desirable even in the absence of --ancestry-path, so I don't think
this is an ancestry-path change. (And from a basic naive usability point
of view I'm much more interested in improving the more obvious modes
than the rather more obscure --ancestry-path.)

Ancestry path forces side branches to be ignored - it's the simple
case for ignoring (and understanding) side branches. But if we let other
modes know where the bottom is, they too can benefit from reliable side
branch logic - we can find out if anything happened on side branches,
but we can also ignore them completely if they turn out to be totally
irrelevant.

When not using ancestry-path, the side branches this patch works on are
thosewhich go off and don't come back - they stub off at some
UNINTERESTING commit other than the bottom(s). If no other limiting is
set, they must have hit an ancestor of our BOTTOM commit(s);
simplify-merges could have potentially pruned away if unlimited. And
this patch restores that pruning ability - simplify-merges can rewrite
them back to just 1 UNINTERESTING merge parent at the boundary (looking
like an ancestry-path boundary), then this patch can chuck the boundary
merge. Hey presto, irrelevant branch now invisible. And the patch also
provides benefits to all other modes.

I'll post v3 of the sequence tomorrow - it includes a new test which
illustrates the changes - it's a 60-or-so-item test set, with about 15
failures in a variety of modes that get fixed by this sequence. I
think that should make an excellent discussion topic. We'll see whether
folks agree with my view about what should and shouldn't be shown...

Kevin

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Another use of @?

2013-05-04 Thread Matthieu Moy
Ramkumar Ramachandra artag...@gmail.com writes:

 On Matthieu's note, I have a comment: symbolic refs are an absolute
 dead end.  We didn't think of it from the start, and it's too late
 now.  Do NOT go there: from my investigation, I believe that hooking
 up everything to the revision parser is the way forward.

My comment was not about the solution, but about the problem (which
seemed to have been misunderstood). The question seems to be get the
reference with the same names as what HEAD points to, but on remote A,
and the points to part is about symbolic references.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Add porcelain command to revert a single staged file to its HEAD state while preserving its staged state

2013-05-04 Thread Dimitar Bonev
On Sat, May 4, 2013 at 9:48 PM, Jonathan Nieder jrnie...@gmail.com wrote:
 Is there no way to convince PowerShell to treat the output of a
 command as binary data with no particular encoding?

The best I could find out is to pipe the output to set-content:

git show HEAD:targetfile | set-content targetfile

The default console output redirection pipes the output to Out-File
which encodes the resulting file by default with little endian unicode
encoding, but it can be overridden by providing an argument:

git show HEAD:targetfile | Out-File -encoding utf8 targetfile

Also if I provide 'default' encoding to Out-File it produces the exact
same result as set-content command:

git show HEAD:targetfile | Out-File -encoding default targetfile

The API docs state that Default uses the encoding of the system's
current ANSI code page. So I guess it is system dependent, it could be
the case for set-content also, but at the very least set-content is
shorter to write.

On Sat, May 4, 2013 at 11:01 PM, Junio C Hamano gits...@pobox.com wrote:
 Junio C Hamano gits...@pobox.com writes:
 But if your result is _also_ something worth saving, what would you
 do?  git add to update the index will trash the work that was in
 the index, and that is by definition unrelated to what you worked on
 in the working tree (you wanted to start from the version in the
 HEAD, not from the version in the index, so the end result is likely
 to lack the work you saved in the index).

 As Thomas said, I think a more reasonable workflow would begin by
 saving the somewhat worth saving state you have in your index as a
 WIP commit, i.e.

   git commit -m wip

 When I experiment starting from a clean slate (after saving away
 such a WIP commit), I would then do this:

 git checkout HEAD^


Actually this is not the case as I tried to explain with the 'git
commit' followed by 'git checkout HEAD~1 -- targetfile' followed by
'git commit --amend' example. The index and the working dir states are
very well related. Lets imagine that I am adding an MVC feature X - it
could be implemented with 3 or more files. If I stage the files and
came up with an idea that requires a major rewrite of one of these
files - lets say the controller one - then it is more convenient to
checkout the file's HEAD state and build on top of it - I had been
doing just that right before staging - building the previous
implementation so this is so familiar and still recent in time. If the
new controller implementation is less acceptable than the old one I
just commit, otherwise I stage the new implementation and just commit.
So simple, so common workflow.

One more argument against the suggestion of doing a commit ahead of
time is that I like to think in separation to reduce complexity - in
particular I like to think only for the working dir and index states,
commits - I treat them as finished work. If I have to amend a commit,
it is about fixing a mistake - adding/removing a wrong file, fixing a
typo, that sort of things and not for actual work to be done.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/7] shorten_unambiguous_ref(): Allow shortening refs/remotes/origin/HEAD to origin

2013-05-04 Thread Johan Herland
When expanding shorthand refs to full ref names (e.g. in dwim_ref()),
we use the ref_rev_parse_rules list of expansion patterns. This list
allows origin to be expanded into refs/remotes/origin/HEAD, by
using the refs/remotes/%.*s/HEAD pattern from that list.

shorten_unambiguous_ref() exists to provide the reverse operation:
turning a full ref name into a shorter (but still unambiguous) name.
It does so by matching the given refname against each pattern from
the ref_rev_parse_rules list (in reverse), and extracting the short-
hand name from the matching rule.

However, when given refs/remotes/origin/HEAD it fails to shorten it
into origin, because we misuse the sscanf() function when matching
refs/remotes/origin/HEAD against refs/remotes/%.*s/HEAD: We end
up calling sscanf like this:

  sscanf(refs/remotes/origin/HEAD, refs/remotes/%s/HEAD, short_name)

In this case, sscanf() will match the initial refs/remotes/ part, and
then match the remainder of the refname against the %s, and place it
(origin/HEAD) into short_name. The part of the pattern following the
%s format is never verified, because sscanf() apparently does not
need to do that (it has performed the one expected format extraction,
and will return 1 correspondingly; see [1] for more details).

This patch replaces the misuse of sscanf() with a fairly simple function
that manually matches the refname against patterns, and extracts the
shorthand name.

Also a testcase verifying refs/remotes/origin/HEAD - origin has
been added.

[1]: If we assume that sscanf() does not do a verification pass prior
to format extraction, there is AFAICS _no_ way for sscanf() - having
already done one or more format extractions - to indicate to its caller
that the input fails to match the trailing part of the format string.
In other words, AFAICS, the scanf() family of function will only verify
matching input up to and including the last format specifier in the
format string. Any data following the last format specifier will not be
verified. Yet another reason to consider the scanf functions harmful...

Cc: Bert Wesarg bert.wes...@googlemail.com
Signed-off-by: Johan Herland jo...@herland.net
---
 refs.c  | 82 +++--
 t/t6300-for-each-ref.sh | 12 
 2 files changed, 43 insertions(+), 51 deletions(-)

diff --git a/refs.c b/refs.c
index d17931a..7231f54 100644
--- a/refs.c
+++ b/refs.c
@@ -2945,80 +2945,60 @@ struct ref *find_ref_by_name(const struct ref *list, 
const char *name)
return NULL;
 }
 
-/*
- * generate a format suitable for scanf from a ref_rev_parse_rules
- * rule, that is replace the %.*s spec with a %s spec
- */
-static void gen_scanf_fmt(char *scanf_fmt, const char *rule)
+int shorten_ref(const char *refname, const char *pattern, char *short_name)
 {
-   char *spec;
-
-   spec = strstr(rule, %.*s);
-   if (!spec || strstr(spec + 4, %.*s))
-   die(invalid rule in ref_rev_parse_rules: %s, rule);
-
-   /* copy all until spec */
-   strncpy(scanf_fmt, rule, spec - rule);
-   scanf_fmt[spec - rule] = '\0';
-   /* copy new spec */
-   strcat(scanf_fmt, %s);
-   /* copy remaining rule */
-   strcat(scanf_fmt, spec + 4);
-
-   return;
+   /*
+* pattern must be of the form [pre]%.*s[post]. Check if refname
+* starts with [pre] and ends with [post]. If so, write the
+* middle part into short_name, and return the number of chars
+* written (not counting the added NUL-terminator). Otherwise,
+* if refname does not match pattern, return 0.
+*/
+   size_t pre_len, post_start, post_len, match_len;
+   size_t ref_len = strlen(refname);
+   char *sep = strstr(pattern, %.*s);
+   if (!sep || strstr(sep + 4, %.*s))
+   die(invalid pattern in ref_rev_parse_rules: %s, pattern);
+   pre_len = sep - pattern;
+   post_start = pre_len + 4;
+   post_len = strlen(pattern + post_start);
+   if (pre_len + post_len = ref_len)
+   return 0; /* refname too short */
+   match_len = ref_len - (pre_len + post_len);
+   if (strncmp(refname, pattern, pre_len) ||
+   strncmp(refname + ref_len - post_len, pattern + post_start, 
post_len))
+   return 0; /* refname does not match */
+   memcpy(short_name, refname + pre_len, match_len);
+   short_name[match_len] = '\0';
+   return match_len;
 }
 
 char *shorten_unambiguous_ref(const char *refname, int strict)
 {
int i;
-   static char **scanf_fmts;
-   static int nr_rules;
char *short_name;
 
-   /* pre generate scanf formats from ref_rev_parse_rules[] */
-   if (!nr_rules) {
-   size_t total_len = 0;
-
-   /* the rule list is NULL terminated, count them first */
-   for (; ref_rev_parse_rules[nr_rules]; nr_rules++)
-   /* no +1 because strlen(%s)  strlen(%.*s) */
-   

[PATCH 2/7] t7900: Start testing usability of namespaced remote refs

2013-05-04 Thread Johan Herland
Some users are interested in fetching remote refs into a separate namespace
in the local repo. E.g. instead of the usual remote config:

  [remote origin]
fetch = +refs/heads/*:refs/remotes/origin/*
url = ...

they want to keep remote tags separate from local tags, and they may also
want to fetch other ref types:

  [remote origin]
fetch = +refs/heads/*:refs/remotes/origin/heads/*
fetch = +refs/tags/*:refs/remotes/origin/tags/*
fetch = +refs/notes/*:refs/remotes/origin/notes/*
fetch = +refs/replace/*:refs/remotes/origin/replace/*
tagopt = --no-tags
url = ...

This configuration creates a separate namespace under refs/remotes/origin/*
mirroring the structure of local refs (under refs/*) where all the relevant
refs from the 'origin' remote can be found.

This patch introduces a test whose main purpose is to verify that git will
work comfortably with this kind of setup. For now, we only verify that it
is possible (though not exactly easy) to establish a clone with the above
configuration, and that fetching into it yields the expected result.

Signed-off-by: Johan Herland jo...@herland.net
---
 t/t7900-working-with-namespaced-remote-refs.sh | 88 ++
 1 file changed, 88 insertions(+)
 create mode 100755 t/t7900-working-with-namespaced-remote-refs.sh

diff --git a/t/t7900-working-with-namespaced-remote-refs.sh 
b/t/t7900-working-with-namespaced-remote-refs.sh
new file mode 100755
index 000..af03ac9
--- /dev/null
+++ b/t/t7900-working-with-namespaced-remote-refs.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+test_description='testing end-user usability of namespaced remote refs
+
+Set up a local repo with namespaced remote refs, like this:
+
+[remote origin]
+   fetch = +refs/heads/*:refs/remotes/origin/heads/*
+   fetch = +refs/tags/*:refs/remotes/origin/tags/*
+   fetch = +refs/notes/*:refs/remotes/origin/notes/*
+   fetch = +refs/replace/*:refs/remotes/origin/replace/*
+   tagopt = --no-tags
+   url = ...
+
+Test that the usual end-user operations work as expected with this setup.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup server repo' '
+   git init server 
+   (
+   cd server 
+   test_commit server_master_a 
+   git checkout -b other 
+   test_commit server_other_b 
+   git checkout master 
+   test_commit server_master_b
+   )
+'
+
+server_master_a=$(git --git-dir=server/.git rev-parse --verify server_master_a)
+server_master_b=$(git --git-dir=server/.git rev-parse --verify server_master_b)
+server_other_b=$(git --git-dir=server/.git rev-parse --verify server_other_b)
+
+cat  expect.refspecs  EOF
++refs/heads/*:refs/remotes/origin/heads/*
++refs/tags/*:refs/remotes/origin/tags/*
++refs/notes/*:refs/remotes/origin/notes/*
++refs/replace/*:refs/remotes/origin/replace/*
+EOF
+
+cat  expect.show-ref  EOF
+$server_master_b refs/heads/master
+$server_master_b refs/remotes/origin/heads/master
+$server_other_b refs/remotes/origin/heads/other
+$server_master_a refs/remotes/origin/tags/server_master_a
+$server_master_b refs/remotes/origin/tags/server_master_b
+$server_other_b refs/remotes/origin/tags/server_other_b
+EOF
+
+test_clone() {
+   ( cd $1  git config --get-all remote.origin.fetch )  actual.refspecs 

+   test_cmp expect.refspecs actual.refspecs 
+   ( cd $1  git show-ref )  actual.show-ref 
+   test_cmp expect.show-ref actual.show-ref
+}
+
+test_expect_failure 'clone with namespaced remote refs' '
+   git clone server client \
+   --config 
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/heads/* \
+   --config 
remote.origin.fetch=+refs/tags/*:refs/remotes/origin/tags/* \
+   --config 
remote.origin.fetch=+refs/notes/*:refs/remotes/origin/notes/* \
+   --config 
remote.origin.fetch=+refs/replace/*:refs/remotes/origin/replace/* \
+   --config remote.origin.tagopt --no-tags 
+   test_clone client
+'
+
+# Work-around for the above failure
+test_expect_success 'work-around clone with namespaced remote refs' '
+   rm -rf client 
+   git init client 
+   (
+   cd client 
+   git remote add origin ../server 
+   git config --unset-all remote.origin.fetch 
+   git config --add remote.origin.fetch 
+refs/heads/*:refs/remotes/origin/heads/* 
+   git config --add remote.origin.fetch 
+refs/tags/*:refs/remotes/origin/tags/* 
+   git config --add remote.origin.fetch 
+refs/notes/*:refs/remotes/origin/notes/* 
+   git config --add remote.origin.fetch 
+refs/replace/*:refs/remotes/origin/replace/* 
+   git config remote.origin.tagopt --no-tags 
+   git fetch 
+   git checkout master
+   ) 
+   test_clone client
+'
+
+test_done
-- 
1.8.1.3.704.g33f7d4f

--
To unsubscribe from this list: send the line 

[PATCH 3/7] t7900: Demonstrate failure to expand $remote/$branch according to refspecs

2013-05-04 Thread Johan Herland
This test verifies that the following expressions all evaluate to the
full refname refs/remotes/origin/heads/master:

 - refs/remotes/origin/heads/master
 - remotes/origin/heads/master
 - origin/heads/master
 - origin/master

Currently the last of these fail, because the $remote/$branch syntax only
works for remotes with conventional (refs/heads/*:refs/remotes/origin/*)
refspecs.

In order for users of namespaced remote refs (or any other unconventional
refspec configuration) to be able to use the $remote/$branch syntax, we
need to extend the parsing of $remote/$branch expressions to take the
configured refspecs into account (i.e. look up the fetch refspecs for
$remote, and map refs/heads/$branch through the refspecs to find the
corresponding remote-tracking branch name).

Mirroring the expansion of the above 4 expressions into the full refname,
the same 4 expression should also be shortened into origin/master when
abbreviating them into their shortest unambiguous representation, e.g.
when running git rev-parse --abbrev-ref on them. A (currently failing)
test verifying this behavior is also added by this patch.

Signed-off-by: Johan Herland jo...@herland.net
---
 t/t7900-working-with-namespaced-remote-refs.sh | 28 ++
 1 file changed, 28 insertions(+)

diff --git a/t/t7900-working-with-namespaced-remote-refs.sh 
b/t/t7900-working-with-namespaced-remote-refs.sh
index af03ac9..cc25e76 100755
--- a/t/t7900-working-with-namespaced-remote-refs.sh
+++ b/t/t7900-working-with-namespaced-remote-refs.sh
@@ -85,4 +85,32 @@ test_expect_success 'work-around clone with namespaced 
remote refs' '
test_clone client
 '
 
+test_expect_success 'enter client repo' '
+   cd client
+'
+
+test_expect_failure 'short-hand notation expands correctly for remote-tracking 
branches' '
+   echo refs/remotes/origin/heads/master  expect 
+   git rev-parse --symbolic-full-name refs/remotes/origin/heads/master  
actual 
+   test_cmp expect actual 
+   git rev-parse --symbolic-full-name remotes/origin/heads/master  actual 

+   test_cmp expect actual 
+   git rev-parse --symbolic-full-name origin/heads/master  actual 
+   test_cmp expect actual 
+   git rev-parse --symbolic-full-name origin/master  actual 
+   test_cmp expect actual
+'
+
+test_expect_failure 'remote-tracking branches are shortened correctly' '
+   echo origin/master  expect 
+   git rev-parse --abbrev-ref refs/remotes/origin/heads/master  actual 
+   test_cmp expect actual 
+   git rev-parse --abbrev-ref remotes/origin/heads/master  actual 
+   test_cmp expect actual 
+   git rev-parse --abbrev-ref origin/heads/master  actual 
+   test_cmp expect actual 
+   git rev-parse --abbrev-ref origin/master  actual 
+   test_cmp expect actual
+'
+
 test_done
-- 
1.8.1.3.704.g33f7d4f

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/7] refs.c: Refactor rules for expanding shorthand names into full refnames

2013-05-04 Thread Johan Herland
In preparation for allowing alternative ways of expanding shorthand refs
(like master) into full refnames (like refs/heads/master): Expand
the current ref_rev_parse_rules list into ref_expand_rules, a list of
struct ref_expand_rule objects that encode both an expansion pattern
(e.g. refs/heads/%.*s) and an associated expansion function
(e.g. the code that applies master to refs/heads/%.*s to produce
refs/heads/master). This allows us to later add expansion rules that
do something other than the current purely textual expansion.

The current expansion behavior is encoded in the new ref_expand_txtly()
helper function, which does the mksnpath() call that were previously
performed by all users of ref_rev_parse_rules.

The end result is identical in behavior to the existing code, but makes
it easier to adjust the way ref expansion happens for remote-tracking
branches in future patches

Most of the existing code that uses ref_rev_parse_rules to expand
shorthand refs are converted to use ref_expand_rules instead.

Signed-off-by: Johan Herland jo...@herland.net
---
 cache.h  |  4 
 refs.c   | 46 +-
 refs.h   | 11 +++
 remote.c |  6 +++---
 4 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/cache.h b/cache.h
index 7ce9061..6adab04 100644
--- a/cache.h
+++ b/cache.h
@@ -875,10 +875,6 @@ extern int dwim_log(const char *str, int len, unsigned 
char *sha1, char **ref);
 extern int interpret_branch_name(const char *str, struct strbuf *);
 extern int get_sha1_mb(const char *str, unsigned char *sha1);
 
-extern int refname_match(const char *abbrev_name, const char *full_name, const 
char **rules);
-extern const char *ref_rev_parse_rules[];
-#define ref_fetch_rules ref_rev_parse_rules
-
 extern int create_symref(const char *ref, const char *refs_heads_master, const 
char *logmsg);
 extern int validate_headref(const char *ref);
 
diff --git a/refs.c b/refs.c
index 7231f54..8b02140 100644
--- a/refs.c
+++ b/refs.c
@@ -1724,7 +1724,24 @@ const char *prettify_refname(const char *name)
0);
 }
 
-const char *ref_rev_parse_rules[] = {
+static void ref_expand_txtly(const struct ref_expand_rule *rule,
+char *dst, size_t dst_len,
+const char *shortname, size_t shortname_len)
+{
+   mksnpath(dst, dst_len, rule-pattern, shortname_len, shortname);
+}
+
+const struct ref_expand_rule ref_expand_rules[] = {
+   { ref_expand_txtly, %.*s },
+   { ref_expand_txtly, refs/%.*s },
+   { ref_expand_txtly, refs/tags/%.*s },
+   { ref_expand_txtly, refs/heads/%.*s },
+   { ref_expand_txtly, refs/remotes/%.*s },
+   { ref_expand_txtly, refs/remotes/%.*s/HEAD },
+   { NULL, NULL }
+};
+
+static const char *ref_rev_parse_rules[] = {
%.*s,
refs/%.*s,
refs/tags/%.*s,
@@ -1734,15 +1751,17 @@ const char *ref_rev_parse_rules[] = {
NULL
 };
 
-int refname_match(const char *abbrev_name, const char *full_name, const char 
**rules)
+int refname_match(const char *abbrev_name, const char *full_name,
+ const struct ref_expand_rule *rules)
 {
-   const char **p;
+   const struct ref_expand_rule *p;
const int abbrev_name_len = strlen(abbrev_name);
+   char n[PATH_MAX];
 
-   for (p = rules; *p; p++) {
-   if (!strcmp(full_name, mkpath(*p, abbrev_name_len, 
abbrev_name))) {
+   for (p = rules; p-expand; p++) {
+   p-expand(p, n, sizeof(n), abbrev_name, abbrev_name_len);
+   if (!strcmp(full_name, n))
return 1;
-   }
}
 
return 0;
@@ -1807,21 +1826,22 @@ static char *substitute_branch_name(const char 
**string, int *len)
 int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
 {
char *last_branch = substitute_branch_name(str, len);
-   const char **p, *r;
+   const struct ref_expand_rule *p;
+   const char *r;
int refs_found = 0;
 
*ref = NULL;
-   for (p = ref_rev_parse_rules; *p; p++) {
+   for (p = ref_expand_rules; p-expand; p++) {
char fullref[PATH_MAX];
unsigned char sha1_from_ref[20];
unsigned char *this_result;
int flag;
 
this_result = refs_found ? sha1_from_ref : sha1;
-   mksnpath(fullref, sizeof(fullref), *p, len, str);
+   p-expand(p, fullref, sizeof(fullref), str, len);
r = resolve_ref_unsafe(fullref, this_result, 1, flag);
if (r) {
-   if (!refs_found++)
+   if ((!*ref || strcmp(*ref, r))  !refs_found++)
*ref = xstrdup(r);
if (!warn_ambiguous_refs)
break;
@@ -1838,17 +1858,17 @@ int dwim_ref(const char *str, int len, unsigned char 
*sha1, char **ref)
 int dwim_log(const char *str, int len, unsigned 

[PATCH 5/7] refs.c: Refactor code for shortening full refnames into shorthand names

2013-05-04 Thread Johan Herland
shorten_unambiguous_ref() provides the reverse functionality to the
expansion of shorthand names into full refnames, i.e. it takes a full
refname (like refs/heads/master), and matches it against a pattern
(like refs/heads/%.*s) to produce a shorthand name (like master).

Being the last remaining user of ref_rev_parse_rules list, this patch
converts it to use ref_expand_rules instead. However, as we associated
an expansion function with each expansion rule - to allow for alternative
expansion behavior in the future - we also need to associate a
shortening function with each rule, to allow for the reverse operation
to be customized as well.

Therefore, we add a shorten function to struct ref_expand_rule, to
encode the shortening of a full refname into a shorthand name. The
relevant rule and the full refname is passed as arguments, and the
resulting shorthand name is returned as an allocated string. If the
refname could not be shortened according to the given rule, NULL is
returned.

The reason for moving the allocation of the shorthand name into the
shortening function, is that one assumes the shortening function itself
will best know exactly how much memory is needed to hold the shorthand
string.

Naturally, we provide a shortening function that encodes the current
textual shortening algorithm - called ref_shorten_txtly() - which is
merely a slight refactoring of the former shorten_ref() function.

This patch removes the only remaining user of ref_rev_parse_rules.
It has now been fully replaced by ref_expand_rules. Hence this patch
also removes ref_rev_parse_rules.

Signed-off-by: Johan Herland jo...@herland.net
---
 refs.c | 110 -
 refs.h |   2 ++
 2 files changed, 50 insertions(+), 62 deletions(-)

diff --git a/refs.c b/refs.c
index 8b02140..a866489 100644
--- a/refs.c
+++ b/refs.c
@@ -1731,24 +1731,41 @@ static void ref_expand_txtly(const struct 
ref_expand_rule *rule,
mksnpath(dst, dst_len, rule-pattern, shortname_len, shortname);
 }
 
-const struct ref_expand_rule ref_expand_rules[] = {
-   { ref_expand_txtly, %.*s },
-   { ref_expand_txtly, refs/%.*s },
-   { ref_expand_txtly, refs/tags/%.*s },
-   { ref_expand_txtly, refs/heads/%.*s },
-   { ref_expand_txtly, refs/remotes/%.*s },
-   { ref_expand_txtly, refs/remotes/%.*s/HEAD },
-   { NULL, NULL }
-};
+static char *ref_shorten_txtly(const struct ref_expand_rule *rule,
+  const char *refname)
+{
+   /*
+* rule-pattern must be of the form [pre]%.*s[post]. Check if
+* refname starts with [pre] and ends with [post]. If so,
+* extract the middle part into a newly-allocated buffer, and
+* return it. Else - if refname does not match rule-pattern -
+* return NULL.
+*/
+   size_t pre_len, post_start, post_len, match_len;
+   size_t ref_len = strlen(refname);
+   char *sep = strstr(rule-pattern, %.*s);
+   if (!sep || strstr(sep + 4, %.*s))
+   die(invalid pattern in ref_rev_parse_rules_alt: %s, 
rule-pattern);
+   pre_len = sep - rule-pattern;
+   post_start = pre_len + 4;
+   post_len = strlen(rule-pattern + post_start);
+   if (pre_len + post_len = ref_len)
+   return NULL; /* refname too short */
+   match_len = ref_len - (pre_len + post_len);
+   if (strncmp(refname, rule-pattern, pre_len) ||
+   strncmp(refname + ref_len - post_len, rule-pattern + post_start, 
post_len))
+   return NULL; /* refname does not match */
+   return xstrndup(refname + pre_len, match_len);
+}
 
-static const char *ref_rev_parse_rules[] = {
-   %.*s,
-   refs/%.*s,
-   refs/tags/%.*s,
-   refs/heads/%.*s,
-   refs/remotes/%.*s,
-   refs/remotes/%.*s/HEAD,
-   NULL
+const struct ref_expand_rule ref_expand_rules[] = {
+   { ref_expand_txtly, NULL, %.*s },
+   { ref_expand_txtly, ref_shorten_txtly, refs/%.*s },
+   { ref_expand_txtly, ref_shorten_txtly, refs/tags/%.*s },
+   { ref_expand_txtly, ref_shorten_txtly, refs/heads/%.*s },
+   { ref_expand_txtly, ref_shorten_txtly, refs/remotes/%.*s },
+   { ref_expand_txtly, ref_shorten_txtly, refs/remotes/%.*s/HEAD },
+   { NULL, NULL, NULL }
 };
 
 int refname_match(const char *abbrev_name, const char *full_name,
@@ -2965,68 +2982,35 @@ struct ref *find_ref_by_name(const struct ref *list, 
const char *name)
return NULL;
 }
 
-int shorten_ref(const char *refname, const char *pattern, char *short_name)
-{
-   /*
-* pattern must be of the form [pre]%.*s[post]. Check if refname
-* starts with [pre] and ends with [post]. If so, write the
-* middle part into short_name, and return the number of chars
-* written (not counting the added NUL-terminator). Otherwise,
-* if refname does not match pattern, return 0.
-*/
-   size_t pre_len, post_start, post_len, 

[PATCH 7/7] refs.c: Add rules for resolving refs using remote refspecs

2013-05-04 Thread Johan Herland
The $remote/$branch expression is often used as a shorthand with the
intention of referring to the remote-tracking branch corresponding to
the given $branch in the $remote repo.

Currently, Git resolves this by prepending refs/remotes/ to the given
$remote/$branch expression, resulting in refs/remotes/$remote/$branch,
which is equivalent to the above intention only when conventional
refspecs are being used (e.g. refs/heads/*:refs/remotes/origin/*).
Correspondingly, a full remote-tracking branch name, can only be
shortened to the $remote/$branch form if it textually matches the
refs/remotes/$remote/$branch format.

If unconventional refspecs (e.g. refs/heads/*:refs/remotes/origin/heads/*)
are being used, then the current expansion (refs/remotes/$remote/$branch)
fails to match the remote-tracking branches from the configured remotes.
Ditto for the corresponding shortening.

Instead of doing pure textual expansion (from $remote/$branch to
refs/remotes/$remote/$branch), we should expand by finding all remotes
matching $remote, look up their fetch refspecs, and map
refs/heads/$branch through them to find the appropriate remote-tracking
branch name corresponding to $remote/$branch. This would yield the
correct remote-tracking branch in all cases, both for conventional and
unconventional refspecs.

Likewise, when shortening full refnames for remote-tracking branches into
their shorthand form ($remote/$branch), we should find the refspec with
the RHS that matches the full remote-tracking branch name, and map
through that refspec to produce the corresponding LHS (minus the leading
refs/heads/ part), and from that construct the corresponding
$remote/$branch shorthand.

This patch adds a new expansion method - ref_expand_refspec() - and a
corresponding shortening method - ref_shorten_refspec() - that implements
the remote refspec traversal and expanding/shortening logic described
above. These expand/shorten methods complement the existing
ref_expand_txtly() and ref_shorten_txtly() methods that implement the
current textual expanding/shortening logic.

Implementing the proper expanding/shortening of $remote/$branch is now
a simple matter of adding another entry to the ref_expand_rules list,
using the new ref_expand_refspec() and ref_shorten_refspec() functions.

Note that the existing refs/remotes/* textual expansion/shortening rule
is kept to preserve backwards compatibility for refs under refs/remotes/*
that are not covered by any configured refspec.

Signed-off-by: Johan Herland jo...@herland.net
---
 refs.c | 98 +-
 t/t7900-working-with-namespaced-remote-refs.sh | 21 +-
 2 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/refs.c b/refs.c
index 98997c4..18d7188 100644
--- a/refs.c
+++ b/refs.c
@@ -4,6 +4,7 @@
 #include tag.h
 #include dir.h
 #include string-list.h
+#include remote.h
 
 /*
  * Make sure ref is something reasonable to have under .git/refs/;
@@ -1758,12 +1759,102 @@ static char *ref_shorten_txtly(const struct 
ref_expand_rule *rule,
return xstrndup(refname + pre_len, match_len);
 }
 
+struct ref_expand_refspec_helper_data {
+   const struct ref_expand_rule *rule;
+   char *dst;
+   size_t dst_len;
+   const char *src;
+   size_t src_len;
+};
+
+static int ref_expand_refspec_helper(struct remote *remote, void *cb_data)
+{
+   struct ref_expand_refspec_helper_data *cb = cb_data;
+   struct refspec query;
+   char refspec_src[PATH_MAX];
+   size_t ref_start = strlen(remote-name) + 1;
+   if (prefixcmp(cb-src, remote-name) ||
+   cb-src_len = ref_start ||
+   cb-src[ref_start - 1] != '/')
+   return 0;
+
+   mksnpath(refspec_src, sizeof(refspec_src), cb-rule-pattern,
+cb-src_len - ref_start, cb-src + ref_start);
+
+   memset(query, 0, sizeof(struct refspec));
+   query.src = refspec_src;
+   if ((!remote_find_tracking(remote, query)) 
+   strlen(query.dst)  cb-dst_len) {
+   strcpy(cb-dst, query.dst);
+   return 1;
+   }
+   return 0;
+}
+
+static void ref_expand_refspec(const struct ref_expand_rule *rule,
+  char *dst, size_t dst_len,
+  const char *shortname, size_t shortname_len)
+{
+   /*
+* Given shortname of the form $remote/$ref, see if there is a
+* fetch refspec configured for $remote whose lhs matches
+* rule-pattern % $ref, and use the corresponding rhs of that
+* mapping as the expanded result of $remote/$ref.
+*/
+   const void *has_slash = memchr(shortname, '/', shortname_len);
+   struct ref_expand_refspec_helper_data cb = {
+   rule, dst, dst_len, shortname, shortname_len };
+   dst[0] = '\0';
+   if (has_slash)
+   for_each_remote(ref_expand_refspec_helper, cb);
+}
+
+static int ref_shorten_refspec_helper(struct remote 

Re: jn/config-ignore-inaccessible (Re: What's cooking in git.git (Apr 2013, #10; Mon, 29))

2013-05-04 Thread Junio C Hamano
Jonathan Nieder jrnie...@gmail.com writes:

 Thomas Rast wrote:
 Junio C Hamano gits...@pobox.com writes:

 * jn/config-ignore-inaccessible (2013-04-15) 1 commit
  - config: allow inaccessible configuration under $HOME

  When $HOME is misconfigured to point at an unreadable directory, we
  used to complain and die. This loosens the check.

  I do not think we agreed that this is a good idea, though.

 As a data point: yesterday on IRC, two users complained that they each
 had this problem.

   http://colabti.org/irclogger/irclogger_log/git?date=2013-05-03#l3022
   http://colabti.org/irclogger/irclogger_log/git?date=2013-05-03#l3111

 I think the approach taken in the patch above is a good one.  If
 /etc/gitconfig contains important configuration, it is still not
 ignored, errors other than permissions reading ~/.gitconfig are
 still fatal, and permissions errors accessing ~/.gitconfig are no
 longer fatal because they are expected as something very common
 in normal setups.

OK.  Let's cook it in 'next' for a while and then decide what to do
post 1.8.3; I am perfectly fine with making it graduate to 'master'
immediately after 1.8.3 if everybody thinks this is a good idea.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/7] Make $remote/$branch work with unconventional refspecs

2013-05-04 Thread Junio C Hamano
Johan Herland jo...@herland.net writes:

 The $remote/$branch syntax can be interpreted in two subtly different
 ways:

  1. A shorthand name for the remote-tracking branch corresponding to a
 specific $branch from a specific $remote.

  2. A refname fragment, which - when appended to refs/remotes/ -
 yields the remote-tracking branch corresponding to a specific
 $branch from a specific $remote.

I think both of the above are somewhat distorted views and they go
against all the documentation we have so far.  The real definition
is:

   3. $string (which may happen to have one or more slashes) is used
  by prepending a few common prefixes to see if the result forms
  a full refname, and refs/remotes/ is one of the prefixes.
  origin/master ends up referring refs/remotes/origin/master
  because of this.

 However, when configuring non-default refspecs
 (such as the +refs/heads/*:refs/remotes/origin/heads/*), it becomes
 obvious that the current code follows the latter interpretation: The
 $remote/$branch shorthand will no longer work, and you are forced to
 use $remote/heads/$branch instead.

While I do _not_ think it is _wrong_ to use remotes/origin/heads/*
as a namespace for branches you copy from the 'origin' remote, my
gut feeling is that it is myopic to redefine that origin/master
resolves to refs/remotes/origin/heads/master [*1*].

Step back a bit.

There must be a reason why somebody wants remotes/origin/heads/*
instead of the traditional remotes/origin/* to keep the copies of
branches taken from the origin.

It is because she wants to use the parts of remotes/origin/ that are
outside remote/origin/heads/ to store other things taken from that
remote, no?  They may be changes, pull-requests, notes, etc.

If origin/master were to map to refs/remotes/origin/heads/master and
origin/jh/rtrack were to map to refs/remotes/origin/heads/jh/rtrack,
[*2*] what short-hands hierarchies in refs/remotes/origin/ other
than heads/ would have?

If you do not special case heads/,

$ git merge origin/pull-requests/4

is very straightforward to understand and explain when you use the
definition #3 above.  But if you do, then the above may refer to
origin/heads/pull-requests/4, or perhaps there is no pull-requests/4
branch in the origin and the resolution may have to error out.

While I do not reject refs/remotes/origin/heads/* layout as a
possibility, I am somewhat skeptical that any solution that starts
from the two interpretations above (both of which are flawed, that
only consider what happens to the branches) will yield a generally
useful result.

If the final end result you are shooting for is to introduce an
extra level between the remote name and the branch names, i.e.
heads/, any solution needs to at least have a plan (not necessarily
a detailed design or implementation) for the other hierarchies.  The
possibility to have these other hierarchies per remote is the true
progress that the heads/ at that level can give us; there is not
much point to have heads/ after refs/remotes/origin/, if heads/ is
the only thing that can come there.


[Footnotes]

*1* Unlike the usual cautions from me, this does not have anything
to do with backward compatibility; it is more about forward
thinking.

*2* Wait.
Does origin/jh/rtrack map to refs/remotes/origin/jh/heads/rtrack
which is rtrack branch taken from the origin/jh remote?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


git describe not showing nearest tag

2013-05-04 Thread Jed Brown
$ git rev-list --count v3.2..master
9651
$ git rev-list --count v3.3..master
6378
$ git describe --tags master
v3.2-9651-ga018267

I would have expected to see v3.3-6378-ga018267, given the documentation:

  If multiple tags were found during the walk then the tag which has the
  fewest commits different from the input committish will be selected
  and output. Here fewest commits different is defined as the number of
  commits which would be shown by git log tag..input will be the
  smallest number of commits possible.


What's going on here?


The repository: https://bitbucket.org/petsc/petsc

This repository currently uses only lightweight tags.  As an experiment,
I replaced both v3.2 and v3.3 with annotated tags, but it did not affect
the 'git describe' output.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html