Git development
 help / color / mirror / Atom feed
* Re: [PATCH 19/17] merge: do not fast-forward when merging a tag
From: Junio C Hamano @ 2011-11-09 13:39 UTC (permalink / raw)
  To: git; +Cc: Linus Torvalds
In-Reply-To: <7v8vnpwhxl.fsf@alter.siamese.dyndns.org>

Merging a signed or an annotated tag is meant to trigger the editor for
the integrator to leave a meaningful merge commit log in the history.
Disallow fast-forwarding the merge in such a case to ensure that a merge
commit is always recorded.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/merge.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 3b3e374..99f1429 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1255,8 +1255,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		strbuf_reset(&buf);
 		if (merge_remote_util(commit) &&
 		    merge_remote_util(commit)->obj &&
-		    merge_remote_util(commit)->obj->type == OBJ_TAG)
+		    merge_remote_util(commit)->obj->type == OBJ_TAG) {
 			option_edit = 1;
+			allow_fast_forward = 0;
+		}
 	}
 
 	if (!use_strategies) {

^ permalink raw reply related

* Re: [PATCH v3] post-receive-email: explicitly set Content-Type header
From: Junio C Hamano @ 2011-11-09 14:11 UTC (permalink / raw)
  To: Alexey Shumkin; +Cc: git, Johannes Sixt, Jonathan Nieder
In-Reply-To: <1320836458-24088-1-git-send-email-Alex.Crezoff@gmail.com>

Alexey Shumkin <alex.crezoff@gmail.com> writes:

> Some email clients (e.g. claws-mail) incorrectly display
> message body when there is no Content-Type header and charset
> explicitly defined.
> So, set explicitly Content-Type header. Its charset
> can be defined with hooks.emailcharset config variable.
>
> NB: This above-mentioned charset may differ from i18n.logOutputEncoding,
> because e.g. gitweb expects (for now) i18n.logOutputEncoding set to UTF-8
> to display logs correctly.
>
> Also, introduce hooks.gitopts config variable
> with the default '-c core.quotepath=false'.
> This takes into account that we want to see pretty email-message
> with well-looking messages and list of changed filenames.
> And usually non-ASCII filenames are in the same
> encoding that commit messages are.

(style) Why such an extremely ragged looking line-wrap of paragraphs?

> Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
> ---

In this space, please describe what happened during v1 and v2, and how is
this round different to help reviewers. Pointers to list archive, e.g.
http://thread.gmane.org/gmane.comp.version-control.git/181737, would be
helpful.

People involved in v1/v2 discussion are missing from the Cc: line. Please
do not give a false impression that you are hiding from them.

> diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
> index ba077c1..913be89 100755
> --- a/contrib/hooks/post-receive-email
> +++ b/contrib/hooks/post-receive-email
> @@ -65,6 +65,14 @@
>  #   Default is "--stat --summary --find-copies-harder". Add -p to those
>  #   options to include a unified diff of changes in addition to the usual
>  #   summary output.
> +# hooks.gitopts
> +#   git options for the git diff-tree invocation that shows changes.
> +#   Default is '-c core.quotepath=false' to be able to see non-ASCII filenames
> +#   used in a project.

We do not particularly appreciate a patch that does two unrelated things
("they are both related to post-receive-email" is not an argument).
Wouldn't this be useful even if the change to add hooks.emailcharset
turned out to be unwanted, or vice versa?

> +# hooks.emailcharset
> +#   The charset used in Content-Type header. UTF-8, if not specified.
> +#   It can differ from i18n.logOutputEncoding (not to mess-up with gitweb
> +#   which expects i18n.logOutputEncoding to be set to UTF-8)

Why "UTF-8" instead of "i18n.logoutputencoding" if not specified?

> @@ -234,6 +242,9 @@ generate_email_header()
>  	cat <<-EOF
>  	To: $recipients
>  	Subject: ${emailprefix}$projectdesc $refname_type $short_refname ${change_type}d. $describe
> +	MIME-Version: 1.0
> +	Content-Type: text/plain; charset=$emailcharset
> +	Content-Transfer-Encoding: 8bit
>  	X-Git-Refname: $refname
>  	X-Git-Reftype: $refname_type
>  	X-Git-Oldrev: $oldrev
> ...
> @@ -730,6 +734,19 @@ custom_showrev=$(git config hooks.showrev)
>  maxlines=$(git config hooks.emailmaxlines)
>  diffopts=$(git config hooks.diffopts)
>  : ${diffopts:="--stat --summary --find-copies-harder"}
> +gitopts=$(git config hooks.gitopts || echo '-c core.quotepath=false')
> +emailcharset=$(git config hooks.emailcharset || echo 'UTF-8')
> +
> +projectdesc=$(sed -ne '1p' "$GIT_DIR/description" 2>/dev/null)
> +# Check if the description is unchanged from it's default, and shorten it to
> +# a more manageable length if it is
> +if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null
> +then
> +	projectdesc="UNNAMED PROJECT"
> +fi
> +# Leave description in UTF-8 to be used in the Subject header
> +# But convert it to an hooks.emailcharset encoding to be used in a message body
> +projectdesc_e=$(echo $projectdesc | iconv -f UTF-8 -t $emailcharset 2>/dev/null)

Hmm, this generates a piece of e-mail whose subject line is in UTF-8
(without B/Q quoting) and message body is in totally different encoding.
Is it what mailers really want to see?

It almost seems backwards; converting the payload to UTF-8 and always
sending UTF-8 would be a simpler approach, methinks.

^ permalink raw reply

* Re: [PATCH v3] post-receive-email: explicitly set Content-Type header
From: Alexey Shumkin @ 2011-11-09 15:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Johannes Sixt, Jonathan Nieder
In-Reply-To: <7vy5vpv11n.fsf@alter.siamese.dyndns.org>

> Alexey Shumkin <alex.crezoff@gmail.com> writes:
> 
> > Some email clients (e.g. claws-mail) incorrectly display
> > message body when there is no Content-Type header and charset
> > explicitly defined.
> > So, set explicitly Content-Type header. Its charset
> > can be defined with hooks.emailcharset config variable.
> >
> > NB: This above-mentioned charset may differ from
> > i18n.logOutputEncoding, because e.g. gitweb expects (for now)
> > i18n.logOutputEncoding set to UTF-8 to display logs correctly.
> >
> > Also, introduce hooks.gitopts config variable
> > with the default '-c core.quotepath=false'.
> > This takes into account that we want to see pretty email-message
> > with well-looking messages and list of changed filenames.
> > And usually non-ASCII filenames are in the same
> > encoding that commit messages are.
> 
> (style) Why such an extremely ragged looking line-wrap of paragraphs?
I'm not good enough in English spelling ;(
> 
> > Signed-off-by: Alexey Shumkin <Alex.Crezoff@gmail.com>
> > ---
> 
> In this space, please describe what happened during v1 and v2, and
> how is this round different to help reviewers. Pointers to list
> archive, e.g.
> http://thread.gmane.org/gmane.comp.version-control.git/181737, would
> be helpful.
> 
> People involved in v1/v2 discussion are missing from the Cc: line.
> Please do not give a false impression that you are hiding from them.
Oh, I've missed that moment, sorry all
> 
> > diff --git a/contrib/hooks/post-receive-email
> > b/contrib/hooks/post-receive-email index ba077c1..913be89 100755
> > --- a/contrib/hooks/post-receive-email
> > +++ b/contrib/hooks/post-receive-email
> > @@ -65,6 +65,14 @@
> >  #   Default is "--stat --summary --find-copies-harder". Add -p to
> > those #   options to include a unified diff of changes in addition
> > to the usual #   summary output.
> > +# hooks.gitopts
> > +#   git options for the git diff-tree invocation that shows
> > changes. +#   Default is '-c core.quotepath=false' to be able to
> > see non-ASCII filenames +#   used in a project.
> 
> We do not particularly appreciate a patch that does two unrelated
> things ("they are both related to post-receive-email" is not an
> argument). Wouldn't this be useful even if the change to add
> hooks.emailcharset turned out to be unwanted, or vice versa?
The main reason was that using core.quotepath=false leads to showing
file names "correctly" according to commit messages encoding to make
email-message look pretty.
> 
> > +# hooks.emailcharset
> > +#   The charset used in Content-Type header. UTF-8, if not
> > specified. +#   It can differ from i18n.logOutputEncoding (not to
> > mess-up with gitweb +#   which expects i18n.logOutputEncoding to be
> > set to UTF-8)
> 
> Why "UTF-8" instead of "i18n.logoutputencoding" if not specified?
Well, you're right.
For the explanation:
AFAIU, such hooks are used on central servers to notify involved people
about changes. And AFAIU the same server repos are used with gitweb
(which AFAIK requires i18n.logOutputEncoding=UTF-8)

But in common case "i18n.logoutputencoding" is more suitable.

> 
> > @@ -234,6 +242,9 @@ generate_email_header()
> >  	cat <<-EOF
> >  	To: $recipients
> >  	Subject: ${emailprefix}$projectdesc $refname_type
> > $short_refname ${change_type}d. $describe
> > +	MIME-Version: 1.0
> > +	Content-Type: text/plain; charset=$emailcharset
> > +	Content-Transfer-Encoding: 8bit
> >  	X-Git-Refname: $refname
> >  	X-Git-Reftype: $refname_type
> >  	X-Git-Oldrev: $oldrev
> > ...
> > @@ -730,6 +734,19 @@ custom_showrev=$(git config hooks.showrev)
> >  maxlines=$(git config hooks.emailmaxlines)
> >  diffopts=$(git config hooks.diffopts)
> >  : ${diffopts:="--stat --summary --find-copies-harder"}
> > +gitopts=$(git config hooks.gitopts || echo '-c
> > core.quotepath=false') +emailcharset=$(git config
> > hooks.emailcharset || echo 'UTF-8') +
> > +projectdesc=$(sed -ne '1p' "$GIT_DIR/description" 2>/dev/null)
> > +# Check if the description is unchanged from it's default, and
> > shorten it to +# a more manageable length if it is
> > +if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null
> > +then
> > +	projectdesc="UNNAMED PROJECT"
> > +fi
> > +# Leave description in UTF-8 to be used in the Subject header
> > +# But convert it to an hooks.emailcharset encoding to be used in a
> > message body +projectdesc_e=$(echo $projectdesc | iconv -f UTF-8 -t
> > $emailcharset 2>/dev/null)
> 
> Hmm, this generates a piece of e-mail whose subject line is in UTF-8
> (without B/Q quoting) and message body is in totally different
> encoding. Is it what mailers really want to see?
Here you're right, too. Windows email clients may interpret Subject
header without B/Q quoting in its default Windows charset, and as far as
it may contain non-English project description, so Subject would look
ugly. But I'll try to test with some clients.
> 
> It almost seems backwards; converting the payload to UTF-8 and always
> sending UTF-8 would be a simpler approach, methinks.
Sounds reasonable

^ 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

* 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

* [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: [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

* 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

* [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

* [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 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 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

* 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

* 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: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: 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: 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

* [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: [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

* 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: 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: 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: 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: 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: 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


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