* uncommitted changes in a renamed directory are clobbered on merge
From: Paul Grayson @ 2011-11-10 5:28 UTC (permalink / raw)
To: git
Hello,
While merging with uncommitted changes is strongly discouraged, Git
generally tries to not overwrite your work without warning. However,
there are some situations where Git silently erases uncommitted
changes. Specifically, it seems that if you rename a directory on one
branch, make uncommitted changes to files within that branch, then
merge in another branch, files that would conflict get replaced by the
version on the other branch. We have observed this on Git versions
1.7.5.4 and 1.7.7.3.
I have placed a script demonstrating this problem at
https://gist.github.com/1354160
Here is a shell transcript showing what it looks like:
gitbug$ git init single
Initialized empty Git repository in /home/paul/gitprojects/gitbug/single/.git/
gitbug$ cd single/
gitbug/single$ mkdir test
gitbug/single$ echo "hi" > test/test.txt
gitbug/single$ git add .
gitbug/single$ git commit -am "initial revision"
[master (root-commit) 8be9a1e] initial revision
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 test/test.txt
gitbug/single$ git checkout -b branch1
Switched to a new branch 'branch1'
gitbug/single$ git mv test/ test2
gitbug/single$ git commit -am "renamed test to test2"
[branch1 80d497c] renamed test to test2
1 files changed, 0 insertions(+), 0 deletions(-)
rename {test => test2}/test.txt (100%)
gitbug/single$ git checkout master
Switched to branch 'master'
gitbug/single$ echo "change on master" >> test/test.txt
gitbug/single$ git commit -am "made a change on master"
[master 51d3a75] made a change on master
1 files changed, 1 insertions(+), 0 deletions(-)
gitbug/single$ git checkout branch1
Switched to branch 'branch1'
gitbug/single$ echo "change on branch1" >> test2/test.txt
gitbug/single$ git merge master
Auto-merging test2/test.txt
Merge made by recursive.
test2/test.txt | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
gitbug/single$ cat test2/test.txt
hi
change on master
gitbug/single$
I expected the merge to fail as it usually does when there is a
conflict with uncommitted changes. Instead, it silently deleted the
changes in test.txt.
One of our developers just lost a few hours of work to this bug. Please fix!
Sincerely,
Paul Grayson
^ permalink raw reply
* Re: Bash tab completion for _git_fetch alias is broken on Git 1.7.7.1
From: Junio C Hamano @ 2011-11-10 3:21 UTC (permalink / raw)
To: nathan.f77; +Cc: git
In-Reply-To: <CAPXHQbND61TyU21ckHwRyMYH=P=H7+GZR5KNY8m+qaMEEhEZKQ@mail.gmail.com>
Nathan Broadbent <nathan.f77@gmail.com> writes:
> Dear git mailing list,
>
> I'm assigning the `_git_fetch` bash tab completion to the alias `gf`,
> with the following command:
>
> complete -o default -o nospace -F _git_fetch gf
>
> The tab completion then works fine in git 1.7.0.4, but breaks on git
> 1.7.7.1, with the following error:
We have been cooking for 1.7.8 and have the first release candidate
1.7.8-rc1; could you try it and report what you find out?
^ permalink raw reply
* Bash tab completion for _git_fetch alias is broken on Git 1.7.7.1
From: Nathan Broadbent @ 2011-11-10 2:46 UTC (permalink / raw)
To: git
In-Reply-To: <CAPXHQbPgepSFHX63F+Nt8TJ+znAaVqzzmSZmJqxj2mekhStO-g@mail.gmail.com>
Dear git mailing list,
I'm assigning the `_git_fetch` bash tab completion to the alias `gf`,
with the following command:
complete -o default -o nospace -F _git_fetch gf
The tab completion then works fine in git 1.7.0.4, but breaks on git
1.7.7.1, with the following error:
-bash: [: 2: unary operator expected
Here is the related issue on github (the project is a set of git shortcuts):
https://github.com/ndbroadbent/scm_breeze/issues/11
Thanks for your time, I'd really appreciate some help!
Regards,
Nathan B
^ permalink raw reply
* Re: pretty placeholders for reflog entries
From: Jack Nagel @ 2011-11-10 1:56 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git
In-Reply-To: <20111108054745.GD29643@sigill.intra.peff.net>
On Mon, Nov 7, 2011 at 11:47 PM, Jeff King <peff@peff.net> wrote:
> Sure. I'll re-send the patch once the release is out. That will also
> give Jack and any other interested parties time to comment and test.
Thanks. I used this day, and combined with "--date=", it gets me pretty
close to where I wanted to be. But your comments about reorganizing the
date placeholders make sense, so this is perfectly fine for the time
being.
Thanks again.
Jack
^ permalink raw reply
* RE: Updating Files
From: Ben Walton @ 2011-11-10 1:08 UTC (permalink / raw)
To: greg.brand; +Cc: git
In-Reply-To: <338A71EC3E356A47BF5279971E4EF72A04D860D7F6@WESMSG51.nordsoncorp.local>
Excerpts from Brand, Greg's message of Wed Nov 09 19:54:34 -0500 2011:
Hi Greg,
>               .<filename>.revision   ~ Does GIT have the same, or
> similar options??? I understand with the distributed nature of GIT,
> there may be several ways to accomplish this. It is nice, though, to
> be able to get a clean version without losing changes you may (or
> may not) want to keep.
You've got at least two options to store changes you want to keep but
have them kept out of the way.
1. Commit the change on a branch and leave that branch sitting there.
2. Stash the change with a descriptive note.
If you're on branch master and want to save this change but not have
it 'live' you could do:
git checkout -b save_my_change
git add modified_file
git commit -m 'saving this for later, just in case'
git checkout master
The master branch will not have the change but the save_my_change
branch will. You can see the commit with a command like:
git show save_my_change
That looks up the sha1 for the ref that save_my_change refers to and
then shows the commit object. To re-apply this later, you could merge
the branch to master or cherry pick the sha1 to master (or any other
branch).
The second option, stashing, is likely nicer for this type of thing
but ymmv. In your working tree, with the modified file(s), do:
git stash save -m 'something potentially useful, but maybe not'
Your working tree is now clean and you can see stashes with:
git stash list
You can later get at a stash with git stash apply.
The real gurus may point out something nicer that I didn't think of
too...
Hope this helps.
Thanks
-Ben
--
Ben Walton
Systems Programmer - CHASS
University of Toronto
C:416.407.5610 | W:416.978.4302
^ permalink raw reply
* Re: Updating Files
From: Andrew Ardill @ 2011-11-10 1:05 UTC (permalink / raw)
To: Brand, Greg; +Cc: git@vger.kernel.org
In-Reply-To: <338A71EC3E356A47BF5279971E4EF72A04D860D7F6@WESMSG51.nordsoncorp.local>
An oft heard recommendation when taking up git is to disregard any SCM
you might already know, to clear your mind from an pre-existing
expectations and to learn the tool with a blank slate, so to speak.
This is probably a good idea in your case.
A solid understanding of the core concepts git uses will really help
you - for example, it is very quick and easy to create branches in
git. A branch is just a reference to a snapshot of your files. So, you
can of course have a 'clean' copy and 'dirty' copy, but they would be
contained in different branches, not different files. Once you have
two branches you can easily compare them, merge them, steal from them
- whatever you want.
Other key ideas you may want to understand (in the blank slate sense)
include the index, the working directory and staging commits. I'm sure
others have their own ideas about what they key ideas are too.
If you haven't already, check out the pro-git book[1], it is very good
at explaining these things.
Regards,
Andrew Ardill
[1] http://progit.org/book/
On 10 November 2011 11:54, Brand, Greg <greg.brand@nordsonasymtek.com> wrote:
> Good Day,
>
> Let me begin by describing my SCM experience.
> I am an old school UNIX guy, and grew up with RCS.
> I have written many BASH and CSH scripts for RCS.
>
> Moving on, the next logical step was CVS.
> I've worked with (and administered) CVS for the last 12 years.
> I have also worked with SourceSafe (ugh), Perforce and ClearCase.
>
> I am an avid CVS proponent.
>
> I have Recently changed jobs, to a SourceSafe shop.
> We HAVE to move to something different.
>
> I've played with both Subversion and GIT.
> I REALLY like GIT, but have some questions.
>
>
> For my questions, I will use a CVS comparison sense this is what I'm most familiar with.
>
> - Updating a File:
> ~ CVS's default behavior, is to try to merge changes from the repository into my local copy. Sometimes, this isn't desirable.
> ~ With CVS I can also choose to get a "clean" copy. If the file I'm updating has been modified, CVS will create a backup of the original file before updating to the clean version. The backup file is saved as a "hidden" file, with the format:
> .<filename>.revision
> ~ Does GIT have the same, or similar options??? I understand with the distributed nature of GIT, there may be several ways to accomplish this. It is nice, though, to be able to get a clean version without losing changes you may (or may not) want to keep.
>
>
> Thank you for your help.
> I am sure I will have more questions.
>
> Best Regards,
> Greg Brand
>
>
> _____________________________________________________________________________
> Scanned by IBM Email Security Management Services powered by MessageLabs. For more information please visit http://www.ers.ibm.com
>
> This email is intended only for the use of the party to which it is addressed and may contain information that is privileged, confidential, or protected by law. If you are not the intended recipient you are hereby notified that any dissemination, copying or distribution of the email or its contents is strictly prohibited. If you have received this message in error, please notify us immediately, by replying to the message and deleting it from your computer.
>
> WARNING: Internet communications are not assured to be secure or clear of inaccuracies as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses. Therefore, we do not accept responsibility for any errors or omissions that are present in this email, or any attachment, that have arisen as a result of e-mail transmission.
> _____________________________________________________________________________
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* RE: Updating Files
From: Brand, Greg @ 2011-11-10 0:54 UTC (permalink / raw)
To: git@vger.kernel.org
Good Day,
Let me begin by describing my SCM experience.
I am an old school UNIX guy, and grew up with RCS.
I have written many BASH and CSH scripts for RCS.
Moving on, the next logical step was CVS.
I've worked with (and administered) CVS for the last 12 years.
I have also worked with SourceSafe (ugh), Perforce and ClearCase.
I am an avid CVS proponent.
I have Recently changed jobs, to a SourceSafe shop.
We HAVE to move to something different.
I've played with both Subversion and GIT.
I REALLY like GIT, but have some questions.
For my questions, I will use a CVS comparison sense this is what I'm most familiar with.
- Updating a File:
~ CVS's default behavior, is to try to merge changes from the repository into my local copy. Sometimes, this isn't desirable.
~ With CVS I can also choose to get a "clean" copy. If the file I'm updating has been modified, CVS will create a backup of the original file before updating to the clean version. The backup file is saved as a "hidden" file, with the format:
.<filename>.revision
~ Does GIT have the same, or similar options??? I understand with the distributed nature of GIT, there may be several ways to accomplish this. It is nice, though, to be able to get a clean version without losing changes you may (or may not) want to keep.
Thank you for your help.
I am sure I will have more questions.
Best Regards,
Greg Brand
_____________________________________________________________________________
Scanned by IBM Email Security Management Services powered by MessageLabs. For more information please visit http://www.ers.ibm.com
This email is intended only for the use of the party to which it is addressed and may contain information that is privileged, confidential, or protected by law. If you are not the intended recipient you are hereby notified that any dissemination, copying or distribution of the email or its contents is strictly prohibited. If you have received this message in error, please notify us immediately, by replying to the message and deleting it from your computer.
WARNING: Internet communications are not assured to be secure or clear of inaccuracies as information could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain viruses. Therefore, we do not accept responsibility for any errors or omissions that are present in this email, or any attachment, that have arisen as a result of e-mail transmission.
_____________________________________________________________________________
^ permalink raw reply
* Re: hook for rebase --continue
From: Neal Kreitzinger @ 2011-11-10 0:50 UTC (permalink / raw)
Cc: Matt Graham, git
In-Reply-To: <4EBB1F17.4060907@gmail.com>
On 11/9/2011 6:47 PM, Neal Kreitzinger wrote:
> On 11/7/2011 1:42 PM, Matt Graham wrote:
>> I did some testing and it appears that during a rebase, if I resolve
>> a conflict and call git rebase --continue, the pre-commit hook
>> doesn't run. This means that if I don't resolve the conflict
>> correctly, our check for invalid syntax doesn't get run and creates
>> the risk that someone could push code with invalid syntax, not
>> realizing that the check didn't run.
>>
>> Does anyone else share my expectation that the pre-commit hook
>> should run during a rebase? Or at least for the first commit
>> following a rebase conflict?
>>
>> If not, is there another hook that is triggered by a rebase that I
>> should be using instead?
>>
> You could try creating an alias (e.g. "git rebase-continue") in your
> gitconfig that runs the desired validation logic and then executes git
> rebase --continue. Then you would run "git rebase-continue" instead of "git rebase
> --continue".
>
correction: added the --continue option in the alias example above.
--neal
^ permalink raw reply
* Re: hook for rebase --continue
From: Neal Kreitzinger @ 2011-11-10 0:47 UTC (permalink / raw)
To: Matt Graham; +Cc: git
In-Reply-To: <CALts4TQ545L1d1J0EiUjd7x=WBJpjCCv6UsXZOoGQAC29RqC5g@mail.gmail.com>
On 11/7/2011 1:42 PM, Matt Graham wrote:
> I did some testing and it appears that during a rebase, if I resolve
> a conflict and call git rebase --continue, the pre-commit hook
> doesn't run. This means that if I don't resolve the conflict
> correctly, our check for invalid syntax doesn't get run and creates
> the risk that someone could push code with invalid syntax, not
> realizing that the check didn't run.
>
> Does anyone else share my expectation that the pre-commit hook
> should run during a rebase? Or at least for the first commit
> following a rebase conflict?
>
> If not, is there another hook that is triggered by a rebase that I
> should be using instead?
>
You could try creating an alias (e.g. "git rebase-continue") in your
gitconfig that runs the desired validation logic and then executes git
rebase. Then you would run "git rebase-continue" instead of "git rebase
--continue".
v/r,
neal
^ permalink raw reply
* Re: [PATCH 1/1] apply.c: reject patch without --(ex,in)clude and path outside.
From: Junio C Hamano @ 2011-11-09 23:07 UTC (permalink / raw)
To: Bruce E. Robertson; +Cc: git
In-Reply-To: <1320878942-9811-1-git-send-email-bruce.e.robertson@intel.com>
"Bruce E. Robertson" <bruce.e.robertson@intel.com> writes:
> From: "Bruce E. Robertson" <bruce.e.robertson@intel.com>
>
> Patches are silently ignored when applied with neither --include nor
> --exclude options when the current working dir is not on patch's
> path. This contravenes the principle of least surprise.
I do not necessarily agree but if you think so perhaps the user should be
told about which paths are rejected. In other words, I think it is wrong
to change the exit code to 1 when you are applying a patch that touches
outside your area, but I think it is not wrong if the program warned about
it.
Does your patch behave like that?
> diff --git a/builtin/apply.c b/builtin/apply.c
> index 84a8a0b..162e2aa 100644
> --- a/builtin/apply.c
> +++ b/builtin/apply.c
> @@ -3619,6 +3619,7 @@ static struct lock_file lock_file;
>
> static struct string_list limit_by_name;
> static int has_include;
> +static int has_exclude;
> static void add_name_limit(const char *name, int exclude)
> {
> struct string_list_item *it;
> @@ -3717,9 +3718,13 @@ static int apply_patch(int fd, const char *filename, int options)
> listp = &patch->next;
> }
> else {
> - /* perhaps free it a bit better? */
> - free(patch);
> - skipped_patch++;
> + if ( !has_exclude && !has_include ) {
Style; extra SP inside ().
I am not convinced that the logic here is correct, either. If you have
exclude but not include, and the patch records a path outside your area,
the path will be rejected even if it does not match any of the exclude
patterns. Shouldn't you be treating that case exactly the same as the case
without any exclude patterns?
> + patch->rejected = 1;
Doesn't it trigger "errs" to be set in write_out_results()? This patch is
not free()'ed, but it is not on the "list" either. Where does it go, and
how is that unfreed patch used later in the program?
> + } else {
> + /* perhaps free it a bit better? */
> + free(patch);
> + skipped_patch++;
> + }
> }
> offset += nr;
> }
> @@ -3773,6 +3778,7 @@ static int option_parse_exclude(const struct option *opt,
> const char *arg, int unset)
> {
> add_name_limit(arg, 1);
> + has_exclude = 1;
> return 0;
> }
^ permalink raw reply
* [PATCH 1/1] apply.c: reject patch without --(ex,in)clude and path outside.
From: Bruce E. Robertson @ 2011-11-09 22:49 UTC (permalink / raw)
To: git; +Cc: Bruce E. Robertson
From: "Bruce E. Robertson" <bruce.e.robertson@intel.com>
Patches are silently ignored when applied with neither --include nor
--exclude options when the current working dir is not on patch's
path. This contravenes the principle of least surprise.
"make test" results for this change:
fixed 0
success 8032
failed 0
broken 58
total 8126
Signed-off-by: Bruce E. Robertson <bruce.e.robertson@intel.com>
---
builtin/apply.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 84a8a0b..162e2aa 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3619,6 +3619,7 @@ static struct lock_file lock_file;
static struct string_list limit_by_name;
static int has_include;
+static int has_exclude;
static void add_name_limit(const char *name, int exclude)
{
struct string_list_item *it;
@@ -3717,9 +3718,13 @@ static int apply_patch(int fd, const char *filename, int options)
listp = &patch->next;
}
else {
- /* perhaps free it a bit better? */
- free(patch);
- skipped_patch++;
+ if ( !has_exclude && !has_include ) {
+ patch->rejected = 1;
+ } else {
+ /* perhaps free it a bit better? */
+ free(patch);
+ skipped_patch++;
+ }
}
offset += nr;
}
@@ -3773,6 +3778,7 @@ static int option_parse_exclude(const struct option *opt,
const char *arg, int unset)
{
add_name_limit(arg, 1);
+ has_exclude = 1;
return 0;
}
--
1.7.7.1.432.gca458.dirty
^ permalink raw reply related
* Re: Problem with git-svn with limited SVN access
From: Thomas Rast @ 2011-11-09 22:38 UTC (permalink / raw)
To: Antoine Bonavita; +Cc: git
In-Reply-To: <4EBA63CA.7000201@stickyadstv.com>
Antoine Bonavita wrote:
> ### If I try to add one of the branches manually:
> branches = branches/XXX:refs/remotes/branches/XXX
> > git svn fetch
> One '*' is needed in glob: 'branches/XXX'
I think having several fetch specs should do the trick, although I
cannot easily test with actual permissions.
You can start configuring the repo with
git init
git svn init svn://server/ -T trunk
to get an initial layout. The .git/config will look like
[svn-remote "svn"]
url = svn://server/
fetch = trunk:refs/remotes/trunk
The clue is that the config says 'fetch', not 'trunk'. Much like with
git remotes, you can add more fetch specs along the lines of
fetch = branches/XXX:refs/remotes/svn/XXX
or whatever layout you prefer.
Please tell us whether that works even in the face of restrictions on
branches/ itself :-)
--
Thomas Rast
trast@{inf,student}.ethz.ch
^ permalink raw reply
* Re: RFH: unexpected reflog behavior with --since=
From: Jeff King @ 2011-11-09 22:26 UTC (permalink / raw)
To: Eric Raible; +Cc: git@vger.kernel.org
In-Reply-To: <20111109222032.GB31535@sigill.intra.peff.net>
On Wed, Nov 09, 2011 at 05:20:32PM -0500, Jeff King wrote:
> git log -g --format='%ct %H' |
> awk '{ print $2 if $1 < SOME_TIMESTAMP }'
Hmm, that is obviously not valid awk syntax. My brain has been too fried
by perl. And the comparison goes the wrong way. A (closer to) working
example would be:
git log -g --format='%ct %H' |
perl -alne 'print $F[1] if $F[0] > SOME_TIMESTAMP'
But hopefully you get the point.
-Peff
^ permalink raw reply
* Re: RFH: unexpected reflog behavior with --since=
From: Jeff King @ 2011-11-09 22:20 UTC (permalink / raw)
To: Eric Raible; +Cc: git@vger.kernel.org
In-Reply-To: <20111109220128.GA31535@sigill.intra.peff.net>
On Wed, Nov 09, 2011 at 05:01:28PM -0500, Jeff King wrote:
> In the latter case, we would either need a new specifier (like
> "--reflog-since"), or to rewrite the commit timestamp when we rewrite
> the parent pointers.
>
> The latter has a certain elegance to it (we are making a pretend linear
> history graph out of the reflog, so faking the timestamps to be sensible
> and in order is a logical thing to do) but I worry about lying too much
> in the output. Something like "git log -g --format=%cd" would now have
> the fake timestamp in the output. But then, we already show the fake
> parents in the output, so I don't know that this is any worse.
This patch (which is below) turns out to be absurdly simple. And it
actually still prints the original commit timestamp, because we end up
reparsing it out of the commit object during the pretty-print phase.
So I think the only decision is whether "--since" should respect the
commit timestamps (and be used as a sort of "grep" filter for
timestamps), or whether it should be respecting the fake history we
create when doing a reflog walk.
I think I am leaning towards the latter. It seems to me to be the more
likely guess for what the user would want. And there is real benefit to
doing it in git, since we can stop the traversal early. In the
"grep-like" case, doing it inside git is not really any more efficient
than filtering in a pipeline, like:
git log -g --format='%ct %H' |
awk '{ print $2 if $1 < SOME_TIMESTAMP }'
Of course we could still offer both (with a "--reflog-since" type of
option). We'd also need to turn off the optimization for "--since", and
then check whether "--until" has a similar bug (and offer
"--reflog-until").
diff --git a/reflog-walk.c b/reflog-walk.c
index 5d81d39..2e5b270 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -231,6 +231,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
reflog = &commit_reflog->reflogs->items[commit_reflog->recno];
info->last_commit_reflog = commit_reflog;
commit_reflog->recno--;
+ commit->date = reflog->timestamp;
commit_info->commit = (struct commit *)parse_object(reflog->osha1);
if (!commit_info->commit) {
commit->parents = NULL;
^ permalink raw reply related
* Re: [PATCH 3/3] commit-tree: teach -x <extra>
From: Brad King @ 2011-11-09 22:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1320872495-7545-4-git-send-email-gitster@pobox.com>
On 11/9/2011 4:01 PM, Junio C Hamano wrote:
> By feeding the header part of the original commit with this parameter,
> e.g. -x "$(git cat-file commit $commit | sed -n -e /^$/q -e p)", extra
> headers of another commit can be transplanted to the resulting commit.
One of the interface features typical in git plumbing that I've always liked
is that any place that can pass long strings tends to be implemented using
pipes or files, at least optionally. This is especially helpful for operating
systems that have severe limitations on total command line size.
I suggest a flag (-X ?) that tells commit-tree to treat the commit message
(from wherever it is read) in "cat-file commit" format. Read the extra
header lines from the part before the blank line, and the rest of the message
normally after the blank line. For example:
(git cat-file commit $commit | sed -n -e /^$/q -e p
echo ''
echo 'New commit message') |
git commit-tree -X -p $parent $tree
If we want the original extended headers and the original message:
git cat-file commit $commit | git commit-tree -X -p $parent $tree
-Brad
^ permalink raw reply
* Re: RFH: unexpected reflog behavior with --since=
From: Jeff King @ 2011-11-09 22:01 UTC (permalink / raw)
To: Eric Raible; +Cc: git@vger.kernel.org
In-Reply-To: <4EB9C7D1.30201@nextest.com>
On Tue, Nov 08, 2011 at 04:22:41PM -0800, Eric Raible wrote:
> # It's reported correctly here:
> git log -g --oneline --since=$add_b
>
> # But after a reset no history isn't shown.
> git reset --hard HEAD^
> git log -g --oneline --since=$add_b
>
> Is this a bug? Of course everything is reported when --since isn't used,
> but not so when limited with --since.
It's sort of a bug. And sort of a missing feature.
In the normal revision walking case, git walks the history graph
backwards, hitting the parent of each commit (and when there are
multiple lines of history, we traverse them in commit timestamp order).
So "--since" works not just by omitting non-matching commits from the
output, but also by stopping the traversal when we go too far back in
time. In a sense, this is purely an optimization, as it shouldn't change
the output. But it's an important one, because it makes looking back in
time O(how far back) instead of O(size of all history).
This optimization breaks down badly, of course, in the face of clock
skew (i.e., a commit whose timestamp is further back than its parent).
There are a few tricks we do to avoid small runs of moderate skew, and
in practice it works well.
Now let's look at reflog walking. It's kind of bolted on to the side
of the revision traversal machinery. We walk through the reflog
backwards and pretend that entry N's parent is entry N-1 (you can see
this if you do "git log -g -p", for example; you see the patch versus
the last reflog entry, not the patch against the commit's true parent).
In the case of rewound history (like the reset you showed above), this
means that the history graph will appear to have bad clock skew. The
timestamp of HEAD@{0} is going to be much earlier than its pretend
parent, HEAD@{1}. And the "--since" optimization is going to cut off
traversal, even though there are more interesting commits to be shown.
So in that sense, I think it's a bug, and we should probably disable the
exit-early-from-traversal optimization when we're walking reflogs.
But it may also be a misfeature, because it's not clear what you're
actually trying to limit by. We have commit timestamps, of course, but
when we are walking reflogs, we also have reflog timestamps. Did you
actually want to say "show me all commits in the reflog, in reverse
reflog order, omitting commits that happened before time t"? Or did you
really mean "show me the reflog entries that happened before time t,
regardless of their commit timestamp"?
In the latter case, we would either need a new specifier (like
"--reflog-since"), or to rewrite the commit timestamp when we rewrite
the parent pointers.
The latter has a certain elegance to it (we are making a pretend linear
history graph out of the reflog, so faking the timestamps to be sensible
and in order is a logical thing to do) but I worry about lying too much
in the output. Something like "git log -g --format=%cd" would now have
the fake timestamp in the output. But then, we already show the fake
parents in the output, so I don't know that this is any worse.
-Peff
^ permalink raw reply
* [PATCH 2/3] commit-tree: teach -m/-F options to read logs from elsewhere
From: Junio C Hamano @ 2011-11-09 21:01 UTC (permalink / raw)
To: git
In-Reply-To: <1320872495-7545-1-git-send-email-gitster@pobox.com>
Just like "git commit" does.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/git-commit-tree.txt | 16 +++++++++++--
builtin/commit-tree.c | 43 ++++++++++++++++++++++++++++++++++--
2 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index 02133d5..cfb9906 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -9,7 +9,8 @@ git-commit-tree - Create a new commit object
SYNOPSIS
--------
[verse]
-'git commit-tree' <tree> [(-p <parent commit>)...] < changelog
+'git commit-tree' <tree> [(-p <parent>)...] < changelog
+'git commit-tree' [(-p <parent>)...] [(-m <message>)...] [(-F <file>)...] <tree>
DESCRIPTION
-----------
@@ -17,7 +18,8 @@ This is usually not what an end user wants to run directly. See
linkgit:git-commit[1] instead.
Creates a new commit object based on the provided tree object and
-emits the new commit object id on stdout.
+emits the new commit object id on stdout. The log message is read
+from the standard input, unless `-m` or `-F` options are given.
A commit object may have any number of parents. With exactly one
parent, it is an ordinary commit. Having more than one parent makes
@@ -39,9 +41,17 @@ OPTIONS
<tree>::
An existing tree object
--p <parent commit>::
+-p <parent>::
Each '-p' indicates the id of a parent commit object.
+-m <message>::
+ A paragraph in the commig log message. This can be given more than
+ once and each <message> becomes its own paragraph.
+
+-F <file>::
+ Read the commit log message from the given file. Use `-` to read
+ from the standard input.
+
Commit Information
------------------
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index 92cfbaf..db5b6e5 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -9,7 +9,7 @@
#include "builtin.h"
#include "utf8.h"
-static const char commit_tree_usage[] = "git commit-tree <sha1> [(-p <sha1>)...] < changelog";
+static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-m <message>] <sha1> < changelog";
static void new_parent(struct commit *parent, struct commit_list **parents_p)
{
@@ -51,6 +51,41 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
continue;
}
+ if (!strcmp(arg, "-m")) {
+ if (argc <= ++i)
+ usage(commit_tree_usage);
+ if (buffer.len)
+ strbuf_addch(&buffer, '\n');
+ strbuf_addstr(&buffer, argv[i]);
+ strbuf_complete_line(&buffer);
+ continue;
+ }
+
+ if (!strcmp(arg, "-F")) {
+ int fd;
+
+ if (argc <= ++i)
+ usage(commit_tree_usage);
+ if (buffer.len)
+ strbuf_addch(&buffer, '\n');
+ if (!strcmp(argv[i], "-"))
+ fd = 0;
+ else {
+ fd = open(argv[i], O_RDONLY);
+ if (fd < 0)
+ die_errno("git commit-tree: failed to open '%s'",
+ argv[i]);
+ }
+ if (strbuf_read(&buffer, fd, 0) < 0)
+ die_errno("git commit-tree: failed to read '%s'",
+ argv[i]);
+ if (fd && close(fd))
+ die_errno("git commit-tree: failed to close '%s'",
+ argv[i]);
+ strbuf_complete_line(&buffer);
+ continue;
+ }
+
if (get_sha1(arg, tree_sha1))
die("Not a valid object name %s", arg);
if (got_tree)
@@ -58,8 +93,10 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
got_tree = 1;
}
- if (strbuf_read(&buffer, 0, 0) < 0)
- die_errno("git commit-tree: failed to read");
+ if (!buffer.len) {
+ if (strbuf_read(&buffer, 0, 0) < 0)
+ die_errno("git commit-tree: failed to read");
+ }
if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
strbuf_release(&buffer);
--
1.7.8.rc1.82.gde0f9
^ permalink raw reply related
* [PATCH 3/3] commit-tree: teach -x <extra>
From: Junio C Hamano @ 2011-11-09 21:01 UTC (permalink / raw)
To: git
In-Reply-To: <1320872495-7545-1-git-send-email-gitster@pobox.com>
By feeding the header part of the original commit with this parameter,
e.g. -x "$(git cat-file commit $commit | sed -n -e /^$/q -e p)", extra
headers of another commit can be transplanted to the resulting commit.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/git-commit-tree.txt | 3 ++-
builtin/commit-tree.c | 20 ++++++++++++++++++--
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index cfb9906..060e79d 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -10,7 +10,8 @@ SYNOPSIS
--------
[verse]
'git commit-tree' <tree> [(-p <parent>)...] < changelog
-'git commit-tree' [(-p <parent>)...] [(-m <message>)...] [(-F <file>)...] <tree>
+'git commit-tree' [(-p <parent>)...] [(-m <message>)...] [(-F <file>)...]
+ [(-x <extra>)...]<tree>
DESCRIPTION
-----------
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index db5b6e5..8b0a223 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -9,7 +9,7 @@
#include "builtin.h"
#include "utf8.h"
-static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-m <message>] <sha1> < changelog";
+static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-m <message>] [-x <extra>] <sha1> < changelog";
static void new_parent(struct commit *parent, struct commit_list **parents_p)
{
@@ -32,6 +32,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
unsigned char tree_sha1[20];
unsigned char commit_sha1[20];
struct strbuf buffer = STRBUF_INIT;
+ struct commit_extra_header *extra = NULL, **extra_tail = &extra;
git_config(git_default_config, NULL);
@@ -86,6 +87,20 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
continue;
}
+ if (!strcmp(arg, "-x")) {
+ struct commit_extra_header *x;
+ if (argc <= ++i)
+ usage(commit_tree_usage);
+ x = read_commit_extra_header_lines(argv[i], strlen(argv[i]));
+ if (x) {
+ *extra_tail = x;
+ while (x->next)
+ x = x->next;
+ extra_tail = &x->next;
+ }
+ continue;
+ }
+
if (get_sha1(arg, tree_sha1))
die("Not a valid object name %s", arg);
if (got_tree)
@@ -98,7 +113,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
die_errno("git commit-tree: failed to read");
}
- if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
+ if (commit_tree_extended(buffer.buf, tree_sha1, parents, commit_sha1,
+ NULL, extra)) {
strbuf_release(&buffer);
return 1;
}
--
1.7.8.rc1.82.gde0f9
^ permalink raw reply related
* [PATCH 1/3] commit-tree: update the command line parsing
From: Junio C Hamano @ 2011-11-09 21:01 UTC (permalink / raw)
To: git
In-Reply-To: <1320872495-7545-1-git-send-email-gitster@pobox.com>
We have kept the original "git commit-tree <tree> -p <parent> ..." syntax
forever, but "git commit-tree -p <parent> -p <parent> ... <tree>" would be
more intuitive way to spell it. Dashed flags along with their arguments
come first and then the "thing" argument after the flags.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/commit-tree.c | 31 ++++++++++++++++++-------------
1 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index d083795..92cfbaf 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -27,7 +27,7 @@ static void new_parent(struct commit *parent, struct commit_list **parents_p)
int cmd_commit_tree(int argc, const char **argv, const char *prefix)
{
- int i;
+ int i, got_tree = 0;
struct commit_list *parents = NULL;
unsigned char tree_sha1[20];
unsigned char commit_sha1[20];
@@ -37,20 +37,25 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
if (argc < 2 || !strcmp(argv[1], "-h"))
usage(commit_tree_usage);
- if (get_sha1(argv[1], tree_sha1))
- die("Not a valid object name %s", argv[1]);
- for (i = 2; i < argc; i += 2) {
- unsigned char sha1[20];
- const char *a, *b;
- a = argv[i]; b = argv[i+1];
- if (!b || strcmp(a, "-p"))
- usage(commit_tree_usage);
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (!strcmp(arg, "-p")) {
+ unsigned char sha1[20];
+ if (argc <= ++i)
+ usage(commit_tree_usage);
+ if (get_sha1(argv[i], sha1))
+ die("Not a valid object name %s", argv[i]);
+ assert_sha1_type(sha1, OBJ_COMMIT);
+ new_parent(lookup_commit(sha1), &parents);
+ continue;
+ }
- if (get_sha1(b, sha1))
- die("Not a valid object name %s", b);
- assert_sha1_type(sha1, OBJ_COMMIT);
- new_parent(lookup_commit(sha1), &parents);
+ if (get_sha1(arg, tree_sha1))
+ die("Not a valid object name %s", arg);
+ if (got_tree)
+ die("Cannot give more than one trees");
+ got_tree = 1;
}
if (strbuf_read(&buffer, 0, 0) < 0)
--
1.7.8.rc1.82.gde0f9
^ permalink raw reply related
* [PATCH 0/3] commit-tree updates
From: Junio C Hamano @ 2011-11-09 21:01 UTC (permalink / raw)
To: git
Here are a handful of patches to the lowest level plumbing commit-tree to
teach it to record extended headers. With this series, scripted Porcelain
like rebase--am can propagate the "mergetag" header while rebasing.
Junio C Hamano (3):
commit-tree: update the command line parsing
commit-tree: teach -m/-F options to read logs from elsewhere
commit-tree: teach -x <extra>
Documentation/git-commit-tree.txt | 17 ++++++-
builtin/commit-tree.c | 92 ++++++++++++++++++++++++++++++-------
2 files changed, 89 insertions(+), 20 deletions(-)
--
1.7.8.rc1.82.gde0f9
^ permalink raw reply
* Re: [PATCH] Add abbreviated commit hash to rebase conflict message
From: Junio C Hamano @ 2011-11-09 18:25 UTC (permalink / raw)
To: Sverre Rabbelier
Cc: Ævar Arnfjörð, Jonas Flodén, Eric Herman,
Fernando Vezzosi, Git List
In-Reply-To: <7v4nyg6b9s.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Sverre Rabbelier <srabbelier@gmail.com> writes:
>
>> On Sun, Nov 6, 2011 at 21:27, Junio C Hamano <gitster@pobox.com> wrote:
>>> In what situation does it make sense to say "It came from _this_ commit"?
>>>
>>> I think there is a separate variable that allows any part of the script if
>>> we are being run as a backend of rebase or not, and that is the condition
>>> you are looking for.
>>
>> The closest I could find is:
>>
>> if test -f "$dotest/rebasing"
>>
>> Which is exactly the case when commit is set. Do you prefer the "-f
>> $dotest/rebasing" test or the "-n $commit" one?
>
> Given the variable scoping rules of vanilla shell script, relying on the
> variable $commit is a very bad idea to begin with. I think the variable
> also is used to hold the final commit object name produced by patch
> application elsewhere in the script in the same loop, and I do not think
> existing code clears it before each iteration, as each part of the exiting
> code uses the variable only immediately after that part assigns to the
> variable for its own purpose, and they all know that nobody uses the
> variable as a way for long haul communication media between different
> parts of the script. Unless your patch updated that aspect of the
> lifetime rule for the variable, which I doubt you did, using $commit would
> introduce yet another bug without solving anything, I would think.
I was looking at git-am today for a separate topic. Doesn't it appear to
you that $dotest/original-commit is what serves your purpose the best?
The file is removed before starting to process a new input (i.e. message
in the mbox), created only after we read the from line and determine it is
really the commit we are rebasing, and is left intact until we decide the
patch was applied correctly and write the result out as a tree.
It might be a clean-up to get rid of $dotest/original-commit file, rename
the variable to $original_commit and initialize it to an empty string
where we currently have 'rm -f "$dotest/original-commit"' (and replace the
check 'test -f "$dotest/original-commit"' later in the script with a check
'test -n "$original_commit"'), though.
^ permalink raw reply
* Re: [RFC/PATCH] add update to branch support for "floating submodules"
From: Junio C Hamano @ 2011-11-09 18:01 UTC (permalink / raw)
To: Heiko Voigt; +Cc: git
In-Reply-To: <20111109174027.GA28825@book.fritz.box>
Heiko Voigt <hvoigt@hvoigt.net> writes:
> This is almost ready but I would like to know what users of the
> "floating submodule" think about this.
Thanks for working on this.
I do like to hear from potential users as well, because the general
impression we got was that floating submodules is not a real need of
anybody, but it is merely an inertia of people who (perhaps mistakenly)
thought svn externals that are not anchored to a particular revision is a
feature when it is just a limitation in reality. During the GitTogether'11
we learned that Android that uses floating model does not really have to.
^ permalink raw reply
* [RFC/PATCH] add update to branch support for "floating submodules"
From: Heiko Voigt @ 2011-11-09 17:40 UTC (permalink / raw)
To: git
This adds the capability to configure a branch which submodule update
will use to checkout the tips sha1 instead of the registered one.
It will first attempt to read the configuration directly from the
currently checked out .gitmodules file from the key
submodule.$name.branch. This configuration can be overridden by local
user configuration values. The parameter --branch can be used to
specify/override the branch using the commandline. The parameter
--checkout can be used to switch to the exact model for all submodules.
Such a thing is helpful if a user wants to follow a defined branches tip
in the submodule. Image such a branch is the stable branch for some
central library or similar.
When the newly checked out tip will not match the registered sha1 in the
superproject it will show up as a change as usual. You can imagine this
as a configuration which lets the upstream project tell a user the
branch it usually updates to. The usual revision control is still in
place.
---
This is almost ready but I would like to know what users of the
"floating submodule" think about this.
Documentation/git-submodule.txt | 26 +++++++++--
git-submodule.sh | 47 ++++++++++++++++++++
t/t7406-submodule-update.sh | 93 +++++++++++++++++++++++++++++++++++++++
3 files changed, 162 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 6ec3fef..b8affa3 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -133,9 +133,11 @@ init::
update::
Update the registered submodules, i.e. clone missing submodules and
checkout the commit specified in the index of the containing repository.
- This will make the submodules HEAD be detached unless `--rebase` or
- `--merge` is specified or the key `submodule.$name.update` is set to
- `rebase`, `merge` or `none`.
+ This will make the submodules HEAD be detached. This will not
+ happen if `--rebase`, `--merge` or `--branch` are specified.
+ Also if the key `submodule.$name.update` is set to `rebase`,
+ `merge` or `none`. If `submodule.$name.branch` is set to some
+ local branch this will also not happen.
+
If the submodule is not yet initialized, and you just want to use the
setting as stored in .gitmodules, you can automatically initialize the
@@ -146,7 +148,16 @@ registered submodules, and update any nested submodules within.
+
If the configuration key `submodule.$name.update` is set to `none` the
submodule with name `$name` will not be updated by default. This can be
-overriden by adding `--checkout` to the command.
+overriden by adding `--checkout` to the command. `--checkout` can also
+be used to enforce exact checkout of submodule sha1's.
++
+If the configuration key `submodule.$name.branch` is set to some valid
+branch in the submodule named by `$name` the submodule will be updated
+to the tip of that branch instead of the registered sha1. This option
+can either be set in .gitmodules or via git's configuration. Gits local
+configuration takes precedence over .gitmodules. If you want to override
+the branch checkout you can use the value `HEAD` to tell git to checkout
+exactly the registered sha1.
summary::
Show commit summary between the given commit (defaults to HEAD) and
@@ -252,6 +263,13 @@ OPTIONS
If the key `submodule.$name.update` is set to `rebase`, this option is
implicit.
+--branch::
+ This option is only valid for the update command. You can use
+ this parameter to specify which branch you want to update all
+ submodules to. This is helpful if you want to update all
+ submodules to the tip of a certain branch or need to work on a
+ branch for all submodules for some time.
+
--init::
This option is only valid for the update command.
Initialize all submodules for which "git submodule init" has not been
diff --git a/git-submodule.sh b/git-submodule.sh
index 3adab93..a4b117b 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -465,6 +465,14 @@ cmd_update()
--checkout)
update="checkout"
;;
+ --branch=*)
+ case "$1" in
+ *=*)
+ update="checkout"
+ branch=`expr "z$1" : 'z--[^=]*=\(.*\)'` ;;
+ *)
+ usage ;;
+ esac ;;
--)
shift
break
@@ -504,6 +512,45 @@ cmd_update()
update_module=$(git config submodule."$name".update)
fi
+ if ! test -z "$branch"
+ then
+ branch_module=$branch
+ else
+ if test "$update" != "checkout"
+ then
+ branch_module=$(git config submodule."$name".branch)
+ if test -z "$branch_module"
+ then
+ branch_module=$(git config -f .gitmodules --get submodule."$name".branch)
+ fi
+ fi
+ fi
+
+ if test "$branch_module" = "HEAD"
+ then
+ branch_module=
+ fi
+
+ if ! test -z "$branch_module"
+ then
+ (clear_local_git_env; cd "$path" &&
+ if test ! $nofetch
+ then
+ git-fetch --all >/dev/null 2>/dev/null || exit 1
+ fi) ||
+ die "$(eval_gettext "Unable to fetch submodule in path '\$path'")"
+
+ sha1=$(clear_local_git_env; cd "$path" &&
+ git rev-parse $branch_module) ||
+ say "$(eval_gettext "Unable to find branch '\$branch_module' in submodule path '\$path'")"
+ fi
+
+ if test "$branch" -a "$update" != "checkout"
+ then
+ die "$(eval_gettext "You can not set update='\$update' and
+use a branch for submodule '\$path'")"
+ fi
+
if test "$update_module" = "none"
then
echo "Skipping submodule '$path'"
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 33b292b..517ed83 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -611,4 +611,97 @@ test_expect_success 'submodule update places git-dir in superprojects git-dir re
)
'
+test_expect_success '--branch updates follow the given branch' '
+ git clone . branch &&
+ (cd branch &&
+ git submodule add ./submodule submodule1 &&
+ git submodule add ./submodule submodule2 &&
+ (cd submodule1 &&
+ git rev-parse HEAD >../expected1 &&
+ git checkout HEAD^) &&
+ (cd submodule2 &&
+ git rev-parse HEAD >../expected2 &&
+ git checkout HEAD^) &&
+ git add submodule1 &&
+ git add submodule2 &&
+ git commit -m "add submodule1 and submodule2" &&
+ git submodule update --branch=origin/master &&
+ (cd submodule1 && git rev-parse HEAD >../actual1) &&
+ (cd submodule2 && git rev-parse HEAD >../actual2) &&
+ test_cmp expected1 actual1 &&
+ test_cmp expected2 actual2
+ )
+'
+
+cat >branch/expect_status <<EOF
+ M submodule1
+EOF
+
+check_submodule_one_follows()
+{
+ (cd submodule1 &&
+ git rev-parse origin/master >../expected1 &&
+ git rev-parse HEAD >../actual1) &&
+ (cd submodule2 &&
+ git rev-parse origin/master^ >../expected2 &&
+ git rev-parse HEAD >../actual2) &&
+ test_cmp expected1 actual1 &&
+ test_cmp expected2 actual2 &&
+ git status --porcelain --untracked-files=no >actual_status &&
+ test_cmp expect_status actual_status
+}
+
+check_both_submodules_exact()
+{
+ (cd submodule1 &&
+ git rev-parse origin/master^ >../expected1 &&
+ git rev-parse HEAD >../actual1) &&
+ (cd submodule2 &&
+ git rev-parse origin/master^ >../expected2 &&
+ git rev-parse HEAD >../actual2) &&
+ test_cmp expected1 actual1 &&
+ test_cmp expected2 actual2 &&
+ test -z "$(git status --porcelain --untracked-files=no)"
+}
+
+test_expect_success 'local branch configuration follows branch' '
+ (cd branch &&
+ git submodule update &&
+ check_both_submodules_exact &&
+ git config submodule.submodule1.branch origin/master &&
+ git submodule update &&
+ check_submodule_one_follows
+ )
+'
+
+test_expect_success '.gitmodules branch configuration follows branch' '
+ (cd branch &&
+ git config --unset submodule.submodule1.branch &&
+ git submodule update &&
+ check_both_submodules_exact &&
+ git config -f .gitmodules submodule.submodule1.branch origin/master &&
+ git add .gitmodules &&
+ git commit -m ".gitmodules follows branch" &&
+ git submodule update &&
+ check_submodule_one_follows
+ )
+'
+
+test_expect_success '--checkout commandline overrides branch config' '
+ (cd branch &&
+ git submodule update --checkout &&
+ check_both_submodules_exact
+ )
+'
+
+test_expect_success 'local config overrides .gitmodules branch config' '
+ (cd branch &&
+ git submodule update &&
+ check_submodule_one_follows &&
+ git config submodule.submodule1.branch HEAD &&
+ git submodule update &&
+ check_both_submodules_exact
+ )
+'
+
test_done
--
1.7.7.433.gcf1e7
^ permalink raw reply related
* Re: [git patches] libata updates, GPG signed (but see admin notes)
From: Junio C Hamano @ 2011-11-09 17:26 UTC (permalink / raw)
To: Linus Torvalds
Cc: Ted Ts'o, Shawn Pearce, git, James Bottomley, Jeff Garzik,
Andrew Morton, linux-ide, LKML
In-Reply-To: <CA+55aFyRawm9CoJMiEXDFCX4YTidPOiV4oqSS2d7nNv7Ecw8BQ@mail.gmail.com>
Linus Torvalds <torvalds@linux-foundation.org> writes:
> No, no, don't consider my "put in the merge message" a winner at all.
>
> I personally dislike it, and don't really think it's a wonderful thing
> at all. I really does have real downsides:
>
> - internal signatures really *are* a disaster for maintenance. You
> can never fix them if they need fixing (and "need fixing" may well be
> "you want to re-sign things after a repository format change")
>
> - they are ugly as heck, and you really don't want to see them in
> 99.999% of all cases.
>
> So putting those things iin the merge commit message may have some
> upsides, but it has tons of downsides too.
>
> I think your refs/audit/ idea should be given real thought, because
> maybe that's the right idea.
With the latest round of touch-ups, modulo a few bugs I will be fixing
before the 1.7.8 final, I think what we have is more or less OK in the
shorter term and should be ready for general consumption. The ugliness is
gone, but the issue around internal signatures may remain to be solved in
the longer term. At least, by storing the full contents of the tag today
in an extended header, when we figure out how a detached signature should
really work, we could convert by extracting them from the history.
In a separate message earlier in the thread, you raised another issue.
> I hate how anonymous our branches are. Sure, we can use good names for
> them, but it was a mistake to think we should describe the repository
> (for gitweb), rather than the branch.
>
> Ok, "hate" is a strong word. I don't "hate" it. I don't even think
> it's a major design issue. But I do think that it would have been
> nicer if we had had some branch description model.
At the first glance, our branch model is indeed peculiar in that a branch
does not have a global identity. The scope of its name is local to the
repository, and it is just a pointer into the history. A "note" [*1*] that
can annotate a commit long after the commit is made is not a good way to
describe what a branch is about, because the tip of the branch can advance
beyond the commit that is annotated by such a note. A commit on a branch
does not serve as a good anchoring point to describe the branch.
However, a commit that merges the history of a branch, whether the merged
branch is from a local repository or from a remote one, does serve as a
good anchoring point. The work on a branch is finished as complete as
possible at the time of the merge, and the committer who merges the branch
agrees with both the objective and the implementation of the work done on
the branch, and that is why the merge is made [*2*]. Describing what the
history of the side branch was about in the resulting merge is a perfectly
sensible way to explain the branch. So in that sense, I am very happy with
the way the merge message template uses the pull request tag to let the
lieutenant explain and defend the history behind the tag used for the pull
request. Such an explanation does not have to be keyed with anybody's
local branch name (e.g. "for-linus" would mean different things for
different pull requests even from the same person), but keying it with the
resulting merge commit is a sensible way to leave the record in the
history.
After justifying with the above two paragraphs that it is perfectly
sensible to record the annotations on commits and not on "branch names", I
do agree that we would eventually want to be able to have such annotations
on commits after the fact. Neither "tags" nor "notes" is necessarily a
very good mechanism, however, for the purpose of "signed pull requests"
and "signed commits" [*3*]. Here are some pros and cons:
- tags must be named, but the only thing we need is to be able to look
the contents (with signature if signed) up given a commit object.
Unlike the usual "I want to check out v3.0 release" look-up that goes
from tag names to the commits, annotation look-ups go the other way, do
not have to have a tagname, and having tagname does not help our
look-up in any way. If we want to use tag to annotate various commits
by various people and keep them around, we would need global namespace
that would not cause them to crash (we can work this around by using
the object name of the tag, e.g. renaming 'for-linus' tag to $(git
rev-parse tags/for-linus), but that is merely a workaround of having to
name things that do not have to be named in the first place). As a
local storage machinery for annotations, tags hanging below refs/tags/
(or refs/audit for that matter) hierarchy with their own names is an
inappropriate model.
+ tags can auto-follow the commits when object transfer happens (at least
in the fetch direction), and for the purpose of "signed pull requests"
and "signed commits", this is a desirable property. When a repository
gains a commit, the annotations attached to the commit that are missing
from the receiving repository are automatically transferred from the
place the commit comes from. Annotations given to other commits that
are not transferred into the repository do not come to the repository.
- "git notes" is represented as a commit that records a tree that holds
the entire mapping from commit to its annotations, and the only way to
transferr it is to send it together with its history as a whole. It
does not have the nice auto-following property that transfers only the
relevant annotations.
+ "git notes" maps the commits to its annotations in the right direction;
the object name of an annotated object to its annotation.
In the longer term, I think we would need to extend the system in the
following way:
- Introduce a mapping machanism that can be locally used to map names of
the objects being annotated to names of other objects (most likely
blobs but there is nothing that fundamentally prevents you from
annotating a commit with a tree). The current "git notes" might be a
perfectly suitable representation of this, or it may turn out to be
lacking (I haven't thought things through), but the important point is
that this "mapping store" is _local_. fsck, repack and prune need to be
told that objects that store the annotation are reachable from the
annotated objects.
- Introduce a protocol extension to transfer this mapping information for
objects being transferred in an efficient way. When "rev-list --objects
have..want" tells us that the receiving end (in either fetch/push
direction) would have an object at the end of the primary transfer
(note that I did not say "an object will be sent in this transfer
transaction"; "have" does not come into the picture), we make sure that
missing annotations attached to the object is also transferred, and new
mapping is registered at the receiving end.
The detailed design for the latter needs more thought. The auto-following
of tags works even if nothing is being fetched in the primary transfer
(i.e. "git fetch" && "git fetch" back to back to update our origin/master
with the master at the origin) when a new tag is added to ancient part of
the history that leads to the master at the origin, but this is exactly
because the sending end advertises all the available tags and the objects
they point at so that we can tell what new tags added to an old object is
missing from the receiving end. This obviously would not scale well when
we have tens of thousands of objects to annotate. Perhaps an entry in the
"mapping store" would record:
- The object name of the object being annotated;
- The object name of the annotation;
- The "timestamp", i.e. when the association between the above two was
made--this can be local to the repository and a simple counter would
do.
and also maintain the last "timestamp" this repository sent annotations to
the remote (one timestamp per remote repository). When we push, we would
send annotations pertaining to the object reachable from what we are
pushing (not limited by what they already have, as the whole point of this
exercise is to allow us to transfer annotations added to an object long
after the object was created and sent to the remote) that is newer than
that "timestamp". Similarly, when fetching, we would send the "timestamp"
this repository last fetched annotations from the other end (which means
we would need one such "timestamp" per remote repository) and let the
remote side decide the set of new annotations they added since we last
synched that are on objects reachable from what we "want".
Or something like that.
[Footnote]
*1* By this word, I do not necessarily mean what the "git notes" command
manipulates. A tag that points at a commit is also equally a good vehicle
to annotate a commit after the fact.
*2* For this reason, it may make sense to "commit -S" such a merge
commit. The "mergetag" asserts the authenticity of the pull request from
the lieutenant whose history is being integrated, and the "gpgsig" asserts
the authenticity of the merge itself--the fact that it was made by the
integrator.
*3* I do not mean what "git commit -S" parked in 'pu' produces, which is
to store the signature in the commit. Adding "Signed-off-by:" after the
fact to an existing commit by many people is a more appropriate example.
^ permalink raw reply
* [PATCH] gitk: use "gitk: repo-top-level-dir" as window title
From: Zbigniew Jędrzejewski-Szmek @ 2011-11-09 16:28 UTC (permalink / raw)
To: git, Doug Maxey, Paul Mackerras; +Cc: gitster, Zbigniew Jędrzejewski-Szmek
Previously, when run in a subdirectory, gitk would show the name
of this subdirectory as title, which was misleading. When run with
GIT_DIR set, it would show the cwd, which is even more misleading.
In case of non-bare repos, the .git suffix in the path is skipped.
Signed-off-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
---
gitk-git/gitk | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 4cde0c4..2eaf901 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -18,6 +18,14 @@ proc gitdir {} {
}
}
+proc reponame {} {
+ set n [file normalize [gitdir]]
+ if {[string match "*/.git" $n]} {
+ set n [string range $n 0 end-5]
+ }
+ return [file tail $n]
+}
+
# A simple scheduler for compute-intensive stuff.
# The aim is to make sure that event handlers for GUI actions can
# run at least every 50-100 ms. Unfortunately fileevent handlers are
@@ -11592,6 +11600,8 @@ if {[package vcompare $git_version "1.6.6.2"] >= 0} {
set show_notes "--show-notes"
}
+set appname "gitk"
+
set runq {}
set history {}
set historyindex 0
@@ -11656,7 +11666,7 @@ catch {
}
# wait for the window to become visible
tkwait visibility .
-wm title . "[file tail $argv0]: [file tail [pwd]]"
+wm title . "$appname: [reponame]"
update
readrefs
--
1.7.8.rc0.251.gccd63
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox