How do I modify the commit message (not the topmost one) of a git commit?
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?
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
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?
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
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
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
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)
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
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
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?
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 @?
[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?
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
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
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
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?
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
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)
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
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
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))
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
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 @?
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
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
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
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
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
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
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
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))
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
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
$ 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