Git development
 help / color / mirror / Atom feed
* will git provide `submodule remove` option ?‏
From: Lingcha X @ 2013-02-05 10:32 UTC (permalink / raw)
  To: git@vger.kernel.org

As we all know, git provides `submodule add , init, update, sync, sumary, foreach, status`, but where is `submodule remove`?

will
 I not delete one of them sometime in the future? Although most people 
will not use submodule or one who uses it can remove submodule by hand, providing complete options may be a good idea.

I am not familiar with C, but i can help test it. will anyone finish this feature?

----
Thanks and Best Regards,
lingchax 		 	   		  

^ permalink raw reply

* Re: [PATCH v3 0/8] Hiding refs
From: Michael Haggerty @ 2013-02-05 10:29 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: Junio C Hamano, git, Jeff King, Shawn Pearce
In-Reply-To: <20130205083327.GA4931@elie.Belkin>

On 02/05/2013 09:33 AM, Jonathan Nieder wrote:
> Michael Haggerty wrote:
> 
>> I would again like to express my discomfort about this feature, which is
>> already listed as "will merge to next".  Frankly, I have the feeling
>> that this feature is being steamrolled in before a community consensus
>> has been reached and indeed before many valid points raised by other
>> members of the community have even been addressed.  For example:
> 
> In $dayjob I work with Gerrit, so I think I can start to answer some
> of these questions.
> 
>> * I didn't see a response to Peff's convincing arguments that this
>> should be a client-side feature rather than a server-side feature [1].
> 
> The client can't control the size of the ref advertisement.  That is
> the main motivation if I understood correctly.

Not according to Junio [4]:

  Look at this as a mechanism for the repository owner to control the
  clutter in what is shown to the intended audience of what s/he
  publishes in the repository.  Network bandwidth reduction of
  advertisement is a side effect of clutter reduction, and not
  necessarily the primary goal.

>> * I didn't see an answer to Duy's question [2] about what is different
>> between the proposed feature and gitnamespaces.
> 
> Namespaces are more complicated and don't sit well in existing setups
> involving git repositories whose refs are not namespaced.

Thanks.

>> * I didn't see a response to my worries that this feature could be
>> abused [3].
> 
> Can you elaborate?  Do you mean that through social engineering an
> attacker would convince the server admin to store secrets using a
> hidden ref and enable the upload-archive service?

The upload-archive service is not needed; after patch v3 "7/8" remote
clients are able to retrieve hidden content by SHA1.

Hiderefs creates a "dark" corner of a remote git repo that can hold
arbitrary content that is impossible for anybody to discover but
nevertheless possible for anybody to download (if they know the name of
a hidden reference).  In earlier versions of the patch series I believe
that it was possible to push to a hidden reference hierarchy, which made
it possible to upload dark content.  The new version appears (from the
code) to prohibit adding references in a hidden hierarchy, which would
close the main loophole that I was worried about.  But the documentation
and the unit tests only explicitly say that updates and deletes are
prohibited; nothing is said about adding references (unless "update" is
understood to include "add").  I think the true behavior should be
clarified and tested.

I was worried that somehow this "dark" content could be used for
malicious purposes; for example, pushing compromised code then
convincing somebody to download it by SHA1 with the implicit argument
"it's safe since it comes directly from the project's official
repository".  If it is indeed impossible to populate the dark namespace
remotely then I can't think of a way to exploit it.

> That does sound like a reasonable concern.  Perhaps the documentation
> should be updated along these lines
> 
> 	transfer.hiderefs::
> 		String(s) `upload-pack` and `receive-pack` use to decide
> 		which refs to omit from their initial advertisement.  Use
> 		more than one transfer.hiderefs configuration variables to
> 		specify multiple prefix strings. A ref that are under the
> 		hierarchies listed on the value of this variable is excluded,
> 		and is hidden from `git ls-remote`, `git fetch`, `git push :`,
> 		etc.  An attempt to update or delete a hidden ref by `git push`
> 		is rejected, and an attempt to fetch a hidden ref by `git fetch`
> 		will fail.
> 	+
> 	This setting does not currently affect the `upload-archive` service.
> 
> until someone interested implements the same for upload-archive.

Yes, this sounds reasonable.

>> I also think that the feature is poorly designed.  For example:
> 
> That's another reasonable concern.  It's very hard to get a design
> correct right away, which is presumably part of the motivation of
> getting this into the hands of interested users who can give feedback
> on it.  What would potentially be worth blocking even that is concerns
> about the wire protocol, since it is hard to take back mistakes there.
> 
>> * Why should a repository have exactly one setting for what refs should
>> be hidden?  Wouldn't it make more sense to allow multiple "views" to be
>> defined?:
> 
> How do I request a different view of the repository at
> /path/to/repo.git over the network?  How can we make the common case
> of only one view easy to achieve?  Isn't the multiple-views case
> exactly what gitnamespaces is for?

Hidden references can only be configured by somebody with local access
to the repository being served.  Somebody with that access could also
configure views.  He could also probably organize a mapping from URL ->
(GIT_PATH, GIT_VIEW) and offer several different views of the same
repository.  If the setting of environment variables is thought to
sometimes be too problematic, the default view could be defined via
configuration, too:

[view]
	default = official
[view "official"]
	hiderefs = refs/pull

Or perhaps, if views are made available locally too, then one view could
be designated as the default for transfer purposes:

[transfer]
	defaultview = official

gitnamespaces have the disadvantage that you mentioned yourself earlier.

> [...]
>> * Is it enough to support only reference exclusion (as opposed to
>> exclusion and inclusion rules)?
> 
> The motivating example is turning off advertisement of the
> refs/changes hierarchy.  If and when more complicated cases come up,
> that would presumably be the time to support more complicated
> configuration.

I suppose should the need arise we could later introduce
"transfer.showrefs" and let the longest match to a given reference
(i.e., "transfer.hiderefs" vs. "transfer.showrefs") win.

> [...]
>> * Why should this feature only be available remotely?
> 
> It is about transport.  Ref namespaces have their own set of use cases
> and are a distinct feature.

gitnamespaces offer multiple perspectives of a single object database,
using independent sets of references to define the subset.  Changing a
reference in one namespace has no effect on similarly-named references
in another namespace.

The "views" feature that I vaguely suggested, on the other hand, would
offer multiple subsets of a single set of references, a bit like an SQL
view.  Changing a reference in one view would automatically affect it in
other views that include the reference.  It could be a handy way to
reduce clutter *locally* in the same way that hiderefs would reduce
clutter *remotely*.  But more importantly, both features could be built
on the same foundation.

Michael

[4] http://article.gmane.org/gmane.comp.version-control.git/213984

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* Re: [RFC] Should "log --cc" imply "log --cc -p"?
From: Ævar Arnfjörð Bjarmason @ 2013-02-05 10:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Michael J Gruber, git
In-Reply-To: <7vfw1c3ujo.fsf@alter.siamese.dyndns.org>

On Mon, Feb 4, 2013 at 5:36 PM, Junio C Hamano <gitster@pobox.com> wrote:
> "git log/diff-files -U8" do not need "-p" to enable textual patches,
> for example.  It is "I already told you that I want 8-line context.
> For what else, other than showing textual diff, do you think I told
> you that for?" and replacing "8-line context" with various other
> options that affect patch generation will give us a variety of end
> user complaints that would tell us that C) is more intuitive to
> them.

On a related note I think "--full-diff" should imply "-p" too.

^ permalink raw reply

* Re: [RFC] Should "log --cc" imply "log --cc -p"?
From: Jeff King @ 2013-02-05  9:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Michael J Gruber, git
In-Reply-To: <7vfw1c3ujo.fsf@alter.siamese.dyndns.org>

On Mon, Feb 04, 2013 at 08:36:43AM -0800, Junio C Hamano wrote:

> "git log/diff-files -U8" do not need "-p" to enable textual patches,
> for example.  It is "I already told you that I want 8-line context.
> For what else, other than showing textual diff, do you think I told
> you that for?" and replacing "8-line context" with various other
> options that affect patch generation will give us a variety of end
> user complaints that would tell us that C) is more intuitive to
> them.

Yeah, I'd agree with this. My feeling is that when there are two
options, A and B, and A is a no-op if B is not also specified, that it
makes sense for A to imply B. We do it in several places already (and I
just added some for "git branch --list" recently).

Is "--cc" a no-op when "-p" is not specified? Certainly "-c" is not, but
I do not think you are proposing that. At first glance, "--cc" is
nonsensical without "-p", but what about other xdiff callers? For
example, in:

  git log --cc --stat

the "--cc" is significant. So I don't think it is right for "--cc" to
always imply "-p". But if the rule kicked in only when no other format
had been specified, that might make sense.

-Peff

^ permalink raw reply

* Re: [PATCH v3 7/8] fetch: fetch objects by their exact SHA-1 object names
From: Jeff King @ 2013-02-05  9:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Shawn Pearce
In-Reply-To: <1359571542-19852-8-git-send-email-gitster@pobox.com>

On Wed, Jan 30, 2013 at 10:45:41AM -0800, Junio C Hamano wrote:

> Teach "git fetch" to accept an exact SHA-1 object name the user may
> obtain out of band on the LHS of a pathspec, and send it on a "want"
> message when the server side advertises the allow-tip-sha1-in-want
> capability.

Hmm. The UI on this is a little less nice than I would have hoped. Right
now if you want a ref outside of refs/heads, it's up to you to configure
a refspec or do a one-off fetch of the ref:

  git config --add remote.origin.fetch '+refs/pull/*:refs/pull/*'
  git fetch
  git checkout refs/pull/123/head
  ... inspect the contents ...

Without advertisement, we have to learn that refs/pull/123/head exists
out of band. We can no longer fetch all of the refs/pull hierarchy
preemptively, but we can in theory grab at least that one ref like this:

  git fetch refs/pull/123/head
  git checkout FETCH_HEAD
  ... inspect the contents ...

But that does not work with your patch; instead you have to learn not
just the existence of the ref, but also its sha1. This may seem like a
little thing, since you are already learning of the ref out-of-band,
but:

  1. The full sha1 is more annoying to work with. You'd have to cut and
     paste or otherwise script getting it to fetch.  A human-readable
     ref, though, is much easier to remember. The "refs/pull/N/head"
     pattern is simple to learn and type.

  2. Related to (1) above, is that it may be easier to come up with a
     hidden ref name out of band than the full sha1. E.g., if I am
     looking at https://github.com/me/foo.git/pulls/123, I can easily
     construct the ref from that. Getting the sha1 will take extra
     steps.

  3. You have to do the out-of-band step, which may be inconvenient,
     every time the ref is updated. There is no way to say "just give me
     what is at the tip of refs/pull/123/head".

I think you could solve it by teaching upload-pack to understand refs on
"want" lines and convert them into the pointed-to object.

But taking a step back, this really seems quite inferior to an extension
that would allow the client to share its refspecs with the server. That
would solve the bandwidth efficiency problem for normal fetchers who are
looking at "refs/heads/*", while still giving people who are interested
in "refs/pull/*" (or even a specific refs/pull tip) the information they
need to fetch.

The obvious problem is that the server speaks first. But I recall
somebody suggested a combination of:

  1. For git-over-ssh and git-over-tcp, the server advertises
     tell-me-your-refspecs as it starts advertising.  Client interrupts
     advertisement with refspecs once it sees that it is OK to do so.

     We waste some bandwidth during the round-trip, but there will still
     be a benefit for repos with many refs (I wonder if we could even
     re-order the advertisement to show refs/heads/ first, as they are
     the most likely case to be requested). And as time goes on and the
     majority of clients support tell-me-your-refspecs, the server side
     can introduce a short delay after the first advertisement.

  2. For git-over-http, the client speaks first via the http protocol.
     We can stuff the refspecs into extra query parameters.

It's a little more complicated as a solution, but I feel like it gets
the efficiency without a loss of functionality. And it helps in more
situations than the hidden refs proposal (e.g., fetching refs/heads/foo
can avoid enumerating all of refs/heads/*).

-Peff

^ permalink raw reply

* Re: Assorted contrib/subtree Patches
From: Jakub Suder @ 2013-02-05  9:14 UTC (permalink / raw)
  To: David A. Greene
  Cc: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", John Yani
In-Reply-To: <1360037173-23291-1-git-send-email-greened@obbligato.org>

Can I please unsubscribe from this thing?...

Thanks.

Jakub Suder

On 5 February 2013 05:06, David A. Greene <greened@obbligato.org> wrote:
> All of the patches I have received from others as well as a few of my
> own follow.  Probably the most controversial is a patch to remove
> --annotate.  After some discussion on the list it became clear that we
> really want a more general commit rewrite feature.  Removing
> --annotate means we don't have to also support --unannotate and carry
> both forward as backward-compatibility baggage.
>
> Before --annotate was added, git-subtree would force an annotation of
> "*" on every split commit message.  It now does no such thing so
> there's no need to unannotate anything.
>
> Please review and integrate.  Thanks!
>
>                         -David
>

^ permalink raw reply

* Re: [RFC] Should "log --cc" imply "log --cc -p"?
From: Michael J Gruber @ 2013-02-05  8:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vfw1c3ujo.fsf@alter.siamese.dyndns.org>

Junio C Hamano venit, vidit, dixit 04.02.2013 17:36:
> Michael J Gruber <git@drmicha.warpmail.net> writes:
> 
>> But diffs are on here ("-p"), it's just that the default diff option for
>> merges is to not display them. Well, I admit there's two different ways
>> of thinking here:
>>
>> A) "git log -p" turns on diffs for all commits, and the default diff
>> options is the (non-existing) "--no-show" diff-option for merges.
>>
>> B) "git log -p" applies "-p" to all commits except merge commits.
>>
>> I'm strongly in the A camp,...
> 
> I can personally be trained to think either way, but I suspect that
> we already came halfway to
> 
>   C) "-p" asks for two-way patches, and "-c/--cc" ask for n-way
>      patches (including but not limited to n==2); it is not that -p
>      asks for patch generation and others modify the finer behaviour
>      of patch generation.
> 
> "git log/diff-files -U8" do not need "-p" to enable textual patches,
> for example.  It is "I already told you that I want 8-line context.

That's a good point that I wasn't aware of.

> For what else, other than showing textual diff, do you think I told
> you that for?" and replacing "8-line context" with various other
> options that affect patch generation will give us a variety of end
> user complaints that would tell us that C) is more intuitive to
> them.
> 
> But I do not feel very strongly that I am *right* on this issue, so
> I won't do anything about it hastily right now.

I'm not sure how many of these we have already, but to me it indicates
that we should turn diffs on for log with any diff option that only
makes sense with a diff. That would make the ui more consistent without
taking anything away.

For scripting/aliasing purposes, we have "-s" in order to override any
implied "-p" (as I just learned).

Michael

^ permalink raw reply

* Re: Feature request: Allow extracting revisions into directories
From: Sitaram Chamarty @ 2013-02-05  8:55 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Tomas Carnecky, Robert Clausecker, Michael J Gruber, git
In-Reply-To: <7v7gmo3tte.fsf@alter.siamese.dyndns.org>

On Mon, Feb 4, 2013 at 10:22 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Tomas Carnecky <tomas.carnecky@gmail.com> writes:
>
>> That's what `git checkout` is for. And I would even argue that it's the better
>> choice in your situation because it would delete files from /var/www/foo which
>> you have deleted in your repo. git archive|tar wouldn't do that.
>
> The point about removal is an interesting one.  From that /var/www
> location I guess that you are discussing some webapp, but if you let
> it _write_ into it, you may also have to worry about how to handle
> the case where an update from the source end that comes from the
> checkout and an update by the webapp collide with each other.
>
> You also need to maintain the .git/index file that corresponds to
> what should be in /var/www/foo/ if you go that route.
>
> Just to be sure, I am not saying "checkout" is an inappropriate
> solution to whatever problem you are trying to solve. I am just
> pointing out things you need to be aware of if you take that
> approach.

http://sitaramc.github.com/the-list-and-irc/deploy.html is a fairly
popular URL on #git, where the bot responds to "!deploy" with some
text and this URL.

Just sayin'... :)

^ permalink raw reply

* Re: [PATCH v3 3/8] upload/receive-pack: allow hiding ref hierarchies
From: Jeff King @ 2013-02-05  8:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Shawn Pearce
In-Reply-To: <1359571542-19852-4-git-send-email-gitster@pobox.com>

On Wed, Jan 30, 2013 at 10:45:37AM -0800, Junio C Hamano wrote:

> Teach upload-pack and receive-pack to omit some refs from their
> initial advertisements by paying attention to the transfer.hiderefs
> multi-valued configuration variable.  Any ref that is under the
> hierarchies listed on the value of this variable is excluded from
> responses to requests made by "ls-remote", "fetch", "clone", "push",
> etc.
> 
> A typical use case may be
> 
> 	[transfer]
> 		hiderefs = refs/pull
> 
> to hide the refs that are internally used by the hosting site and
> should not be exposed over the network.

In the earlier review, I mentioned making this per-service, but I see
that is not the case here. Do you have an argument against doing so?

I'm specifically thinking of the way we do refs/pull at GitHub (which we
hide only from receive-pack).  I know that you think it would be cleaner
to hide those, and at some level I agree. But at the same time, the
current mechanism has been in place for some time; changing what we
present via upload-pack is likely to break people's workflows. And I
have not seen complaints about the current system. So unless there is a
compelling reason to do so, I'd rather let the fetcher make the
decision.

Gerrit's refs/changes may be a different story, if they have a large
enough number of them to make upload-pack's ref advertisement
overwhelming.

I'm happy to do the per-service patch on top, but I just expected it
here, so I'm wondering if you are against having the feature.

-Peff

^ permalink raw reply

* Re: [WIP/RFH/RFD/PATCH] grep: allow to use textconv filters
From: Michael J Gruber @ 2013-02-05  8:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jeff King
In-Reply-To: <7vtxps2eb2.fsf@alter.siamese.dyndns.org>

Junio C Hamano venit, vidit, dixit 04.02.2013 18:12:
> Michael J Gruber <git@drmicha.warpmail.net> writes:
> 
>> Recently and not so recently, we made sure that log/grep type operations
>> use textconv filters when a userfacing diff would do the same:
>>
>> ef90ab6 (pickaxe: use textconv for -S counting, 2012-10-28)
>> b1c2f57 (diff_grep: use textconv buffers for add/deleted files, 2012-10-28)
>> 0508fe5 (combine-diff: respect textconv attributes, 2011-05-23)
>>
>> "git grep" currently does not use textconv filters at all, that is
>> neither for displaying the match and context nor for the actual grepping.
>>
>> Introduce a binary mode "--textconv" (in addition to "--text" and "-I")
>> which makes git grep use any configured textconv filters for grepping
>> and output purposes.
>>
>> Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
>> ---
>>
>> Notes:
>>     I'm somehow stuck in textconv/filespec/... hell, so I'm sending this out
>>     in request for help. I'm sure there are people for whom it's a breeze to
>>     get this right.
> 
> Looks like the patch touches the right places in the codepaths that
> need to be updated from a quick read.

I should have added that this coredumps when used on blobs and that
textconv isn't invoked in any case (because it crashes on blobs, and I
haven't implemented tetxconv on worktree files yet).

I'm somehow struggling to use just the right bits from the more diff
centric helpers like fill_textconv or fill_one (which is static so far).

>>     The difficulty is in getting the different cases (blob/sha1 vs.
>>     worktree) right, and in making the changes minimally invasive.
> 
> I think grep_source abstraction was intended to be a way for that,
> and if what it gives you is not sufficient for your needs, extending
> it should not be seen as "invasive" at all.

It seems to me that we textconvified the diff versions of these
abstractions, but not the grep_source abstractions. Doing it at the
source appears to be the right thing.

Michael

^ permalink raw reply

* Re: [PATCH v3 0/8] Hiding refs
From: Jonathan Nieder @ 2013-02-05  8:33 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: Junio C Hamano, git, Jeff King, Shawn Pearce
In-Reply-To: <5110BD18.3080608@alum.mit.edu>

Hi Michael,

Michael Haggerty wrote:

> I would again like to express my discomfort about this feature, which is
> already listed as "will merge to next".  Frankly, I have the feeling
> that this feature is being steamrolled in before a community consensus
> has been reached and indeed before many valid points raised by other
> members of the community have even been addressed.  For example:

In $dayjob I work with Gerrit, so I think I can start to answer some
of these questions.

> * I didn't see a response to Peff's convincing arguments that this
> should be a client-side feature rather than a server-side feature [1].

The client can't control the size of the ref advertisement.  That is
the main motivation if I understood correctly.

> * I didn't see an answer to Duy's question [2] about what is different
> between the proposed feature and gitnamespaces.

Namespaces are more complicated and don't sit well in existing setups
involving git repositories whose refs are not namespaced.

> * I didn't see a response to my worries that this feature could be
> abused [3].

Can you elaborate?  Do you mean that through social engineering an
attacker would convince the server admin to store secrets using a
hidden ref and enable the upload-archive service?

That does sound like a reasonable concern.  Perhaps the documentation
should be updated along these lines

	transfer.hiderefs::
		String(s) `upload-pack` and `receive-pack` use to decide
		which refs to omit from their initial advertisement.  Use
		more than one transfer.hiderefs configuration variables to
		specify multiple prefix strings. A ref that are under the
		hierarchies listed on the value of this variable is excluded,
		and is hidden from `git ls-remote`, `git fetch`, `git push :`,
		etc.  An attempt to update or delete a hidden ref by `git push`
		is rejected, and an attempt to fetch a hidden ref by `git fetch`
		will fail.
	+
	This setting does not currently affect the `upload-archive` service.

until someone interested implements the same for upload-archive.

> I also think that the feature is poorly designed.  For example:

That's another reasonable concern.  It's very hard to get a design
correct right away, which is presumably part of the motivation of
getting this into the hands of interested users who can give feedback
on it.  What would potentially be worth blocking even that is concerns
about the wire protocol, since it is hard to take back mistakes there.

> * Why should a repository have exactly one setting for what refs should
> be hidden?  Wouldn't it make more sense to allow multiple "views" to be
> defined?:

How do I request a different view of the repository at
/path/to/repo.git over the network?  How can we make the common case
of only one view easy to achieve?  Isn't the multiple-views case
exactly what gitnamespaces is for?

[...]
> * Is it enough to support only reference exclusion (as opposed to
> exclusion and inclusion rules)?

The motivating example is turning off advertisement of the
refs/changes hierarchy.  If and when more complicated cases come up,
that would presumably be the time to support more complicated
configuration.

[...]
> * Why should this feature only be available remotely?

It is about transport.  Ref namespaces have their own set of use cases
and are a distinct feature.

Hoping that clarifies,
Jonathan

^ permalink raw reply

* Re: [PATCH v3 0/8] Hiding refs
From: Michael Haggerty @ 2013-02-05  8:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

On 01/30/2013 07:45 PM, Junio C Hamano wrote:
> The third round.
> 
>  - Multi-valued variable transfer.hiderefs lists prefixes of ref
>    hierarchies to be hidden from the requests coming over the
>    network.
> 
>  - A configuration optionally allows uploadpack to accept fetch
>    requests for an object at the tip of a hidden ref.
> 
> Elsewhere, we discussed "delaying ref advertisement" (aka "expand
> refs"), but it is an orthogonal feature and this "hiding refs
> completely from advertisement" series does not attempt to address.
> 
> Patch #2 (simplify request validation), #4 (clarify the codeflow),
> and #5 (use struct ref) are new.  The are all long overdue clean-ups
> for these codepaths.
> 
> The last patch is an illustration why it wouldn't make sense to
> optionally allow pushing into hidden refs, and not meant to be part
> of the series proper.
> 
> For those who missed it, earlier rounds are at:
> 
>     http://thread.gmane.org/gmane.comp.version-control.git/213951
>     http://thread.gmane.org/gmane.comp.version-control.git/214888

I would again like to express my discomfort about this feature, which is
already listed as "will merge to next".  Frankly, I have the feeling
that this feature is being steamrolled in before a community consensus
has been reached and indeed before many valid points raised by other
members of the community have even been addressed.  For example:

* I didn't see a response to Peff's convincing arguments that this
should be a client-side feature rather than a server-side feature [1].

* I didn't see an answer to Duy's question [2] about what is different
between the proposed feature and gitnamespaces.

* I didn't see a response to my worries that this feature could be
abused [3].

I also think that the feature is poorly designed.  For example:

* Why should a repository have exactly one setting for what refs should
be hidden?  Wouldn't it make more sense to allow multiple "views" to be
defined?:

[view "official"]
	hiderefs = refs/pull
	hiderefs = refs/heads/??/*
[view "pu"]
	hiderefs = refs/pull
[view "current"]
	hiderefs = refs/tags/releases

with the view perhaps selected via a server-side environment variable?
This would allow multiple views to be published via different URLs but
referring to the same git repository.

* Is it enough to support only reference exclusion (as opposed to
exclusion and inclusion rules)?  Is it enough to support only reference
selection by hierarchy (for example, how would you hide contributed
branches from your repo)?  Can your configuration scheme be expanded in
a backwards-compatible way if these or other extensions are added later?

* Why should this feature only be available remotely?  It would be handy
to clone everything but usually only see some subset of references in my
daily work: "GIT_VIEW=official gitk --all &".  Or to hide some remote
branches most of the time without having to remove them from my repo:

[view "brief"]
	refs = refs
	refs = !refs/remotes
	refs = refs/remotes/origin
	refs = refs/remotes/my-boss

I think there are still more questions than answers about this feature
and FWIW vote -1 on merging it to next at this time.

Michael

[1] http://article.gmane.org/gmane.comp.version-control.git/214168
[2] http://article.gmane.org/gmane.comp.version-control.git/214070
[3] http://article.gmane.org/gmane.comp.version-control.git/213957

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* [PATCH] Get correct column with for options in command usage
From: Jiang Xin @ 2013-02-05  7:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git List, Jiang Xin

Command usage would not align well if command options are translated,
especially to CJK. Call utf8_strwidth in function usage_argh, so that
the caller will get correct column width.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 parse-options.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/parse-options.c b/parse-options.c
index 67e98..ca0e6 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -473,7 +473,7 @@ int parse_options(int argc, const char **argv, const char *prefix,
 
 static int usage_argh(const struct option *opts, FILE *outfile)
 {
-	const char *s;
+	const char *s, *p;
 	int literal = (opts->flags & PARSE_OPT_LITERAL_ARGHELP) || !opts->argh;
 	if (opts->flags & PARSE_OPT_OPTARG)
 		if (opts->long_name)
@@ -482,7 +482,9 @@ static int usage_argh(const struct option *opts, FILE *outfile)
 			s = literal ? "[%s]" : "[<%s>]";
 	else
 		s = literal ? " %s" : " <%s>";
-	return fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
+	p = opts->argh ? _(opts->argh) : _("...");
+	fprintf(outfile, s, p);
+	return utf8_strwidth(p) + strlen(s) - 2;
 }
 
 #define USAGE_OPTS_WIDTH 24
-- 
1.8.1.1.367.g57acac9.dirty

^ permalink raw reply

* Re: [PATCH v3] status: show the branch name if possible in in-progress info
From: Jonathan Nieder @ 2013-02-05  6:38 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git, Matthieu Moy, Junio C Hamano
In-Reply-To: <1359870807-22817-1-git-send-email-pclouds@gmail.com>

Nguyễn Thái Ngọc Duy wrote:

> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>

Missing description.  Stealing from the link you sent:

	The typical use-case is starting a rebase, do something else, come back
	the day after, run "git status" or make a new commit and wonder what
	in the world's going on. Which branch is being rebased is probably the
	most useful tidbit to help, but the target may help too.

	Ideally, I would have loved to see "rebasing master on origin/master",
	but the target ref name is not stored during rebase, so this patch
	writes "rebasing master on a78c8c98b" as a half-measure to remind
	future users of that potential improvement.

	Signed-off-by: <...>

^ permalink raw reply

* On (re)packing
From: Junio C Hamano @ 2013-02-05  6:35 UTC (permalink / raw)
  To: peff, spearce; +Cc: git

Just a random thought...

"git pack-objects" runs "rev-list --objects" to obtain three
different kinds of information about objects:

 * Reachability.  Objects that appear in the output of rev-list are
   relevant, and those that do not are not;

 * Recency, aka closeness in the time dimension.  Objects that
   appear in the output of rev-list close together appear in the
   history nearby (a commit and its parents, a commit and its tree,
   a tree and its subtree and blob);

 * Paths, aka closeness in the space dimension.  Trees and blobs are
   labelled with paths they are first discovered at.

All of these are necessary for reasonable packing.  We choose only
the reachable objects to pack.  We place objects close in the time
dimension together in the output pack stream.  And we delta objects
close in the space dimension against each other.

Now, we are planning to use object reachability bitmap to speed up
the object enumeration phase of repacking.  This primarily gives us
the reachability information.  Placing objects that are packed close
in existing packs close to each other in the output stream hopefully
may give us good enough approximation of the recency order.  And
reusing the delta will keep good existing delta if both deltified
object and its delta base object are included in the output.

What should happen when we repack two or more packs?  Placing an
object that appears near the beginning of one pack close to another
object that appears near the beginning of the other pack would
probably not make much sense, so the natural extension of emulating
recency order by pack offset would be to place all objects from one
pack together (in their original in-pack offset orde) and then
objects from the other pack together.

More problematic is how to coalesce one delta chain from one pack
with another delta chain from the other pack.  Without having the
path information, we cannot efficiently do this.  Especially if we
are to repack 50 small packs into one, it would be desirable if we
can avoid packing 50 similar objects in their undeltified form.

Assuming that we would want some extra information, in addition to
the bitmaps, to help repacking, and also with the recent "commit
metadata" topic in mind, lets do a back-of-the-envelope enumeration
of what we would want.  Here is a list off the top of my head.

* commits

  99.9% of all commits have no more than two parents.  Assuming that
  we keep this information per-pack, and we will not be packing more
  than 2^32 objects in a pack, we can represent up to two parent
  commits by two int32s to represent their position in the table of
  SHA-1's in the .idx file.  Also we can store another uint32 for
  the commit timestamp (compute the timestamp of the oldest commit
  in the pack and store it as uint64, and represent the commmit
  timestamp of each commit with uint32 (we can represent a pack that
  spans 68 years with this scheme).  Give up storing metainformation
  for any commit whose information cannot fit this scheme (e.g. an
  octopus, or a commit with timestamp way out of line).

  That costs 12 bytes per commit (plus 8-byte for the oldest
  timestamp in the pack).

* tags

  The timestamp can be expressed with a uint32 in the same way as
  commit's timestamp, and the tagged object can be expressed with a
  uint32 in the same way as commit's parent.  Two uint32s

* trees and blobs

  The name hash value is uint32.

If we have other information that are needed for trees and blobs
that fit in two more uint32s, then we can just build a table of
12-byte entries for all objects in the pack.  

Otherwise, we would need a way to have separate table that can be
quickly accessed, going from an object name to either 3 uint32 tuple
(if it is a commit), 2 uint32 tuple (if it is a tag), or a uint32
(others).

Whether we can do a table with uniform entry size or split tables,
once we locate an entry, we can find out the object number in the
SHA-1 table the object refers to (e.g. parents, or tagged) so I do
not think it is a good idea to express object pointer with an
abbreviated SHA-1.  But if we have to build commit-only table, we
may need to use a table with 16-byte entry size, that has 8
hexdigits (i.e. 4-bytes) abbreviated object name of a commit,
followed by the 12 byte commit metainformation, and sort it by the
abbreviated object name.  With the same scheme, another table for
trees and blobs will cost 4-bytes for abbreviated object name as key
and 4-bytes for name-hash payload.  That sounds a bit too wasteful
to my taste.

^ permalink raw reply

* Re: [PATCH 13/13] contrib/subtree: Remove --annotate
From: Junio C Hamano @ 2013-02-05  5:17 UTC (permalink / raw)
  To: David A. Greene
  Cc: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani,
	"David A. Greene <greened
In-Reply-To: <1360037173-23291-14-git-send-email-greened@obbligato.org>

"David A. Greene" <greened@obbligato.org> writes:

> From: "David A. Greene" <greened@obbligato.org>
>
> Remove --annotate.  This obviates the need for an --unannotate
> command.  We really want a more generalized commit message rewrite
> mechanism.

That may be a good goal as the end result, but wouldn't it be a bit
unhelpful to remove these before adding such a "more generalized"
mechanism to replace them?

^ permalink raw reply

* Re: [PATCH 12/13] contrib/subtree: Handle '--prefix' argument with a slash appended
From: Junio C Hamano @ 2013-02-05  5:16 UTC (permalink / raw)
  To: David A. Greene
  Cc: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani,
	"David A. Greene <greened
In-Reply-To: <1360037173-23291-13-git-send-email-greened@obbligato.org>

"David A. Greene" <greened@obbligato.org> writes:

> From: Techlive Zheng <techlivezheng@gmail.com>
>
> 'git subtree merge' will fail if the argument of '--prefix' has a slash
> appended.
>
> Signed-off-by: Techlive Zheng <techlivezheng@gmail.com>
> Signed-off-by: David A. Greene <greened@obbligato.org>
> ---
>  contrib/subtree/git-subtree.sh     |    2 +-
>  contrib/subtree/t/t7900-subtree.sh |   19 +++++++++++++++++++
>  2 files changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
> index c72af95..0493e47 100755
> --- a/contrib/subtree/git-subtree.sh
> +++ b/contrib/subtree/git-subtree.sh
> @@ -82,7 +82,7 @@ while [ $# -gt 0 ]; do
>  		--annotate) annotate="$1"; shift ;;
>  		--no-annotate) annotate= ;;
>  		-b) branch="$1"; shift ;;
> -		-P) prefix="$1"; shift ;;
> +		-P) prefix="${1%/}"; shift ;;

While it may not be a bad change per-se, I have to wonder if it is
worth special casing "--prefix=foo/", that should have been spelled
as "--prefix=foo", while still failing misspelling like "--prefix=foo//"
and possibly other forms, perhaps "--prefix=foo//bar/baz"?

^ permalink raw reply

* Re: [PATCH 11/13] contrib/subtree: Make each test self-contained
From: Junio C Hamano @ 2013-02-05  5:13 UTC (permalink / raw)
  To: David A. Greene
  Cc: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani,
	"David A. Greene <greened
In-Reply-To: <1360037173-23291-12-git-send-email-greened@obbligato.org>

"David A. Greene" <greened@obbligato.org> writes:

> +test_create_commit() (
> +	repo=$1
> +	commit=$2
> +	cd "$repo"
> +	mkdir -p "$(dirname "$commit")"
> +	echo "$commit" > "$commit"

Style.

> +	git add "$commit"
> +	git commit -m "$commit"
> +)

Very nice, but don't we want to check for possible errors in any of
the above commands?

>  last_commit_message()
>  {
>  	git log --pretty=format:%s -1
>  }
>  
> +#
> +# Tests for 'git subtree add'
> +#
>  
> -test_expect_success 'fetch subproj history' '
> -		git fetch ./subproj sub1 &&
> -		git branch sub1 FETCH_HEAD
> -'
>  
>  test_expect_success 'no pull from non-existant subtree' '
> -		test_must_fail git subtree pull --prefix=subdir ./subproj sub1
> +	test_create_repo "$test_count" &&
> +	test_create_repo "$test_count/subproj" &&
> +	test_create_commit "$test_count" main1 &&
> +	test_create_commit "$test_count/subproj" sub1 &&
> +	(
> +		cd "$test_count" &&
> +		git fetch ./subproj master &&
> +		test_must_fail git subtree pull --prefix=subdir ./subproj master
> +	)
>  '

The goal of making each tests indenendent is a very good one, but
we'd really prefer not to see $test_count which is an implementation
detail of the test framework to be used like this.  It will make it
unnecessarily harder to improve the test framework (e.g. it may want
to stop using the $test_count variable).

This is not limited to this variable, but all other $test_anything
variable.  Earlier I wanted to update the definition of test_tick
which happens to be decimal number of seconds since epoch, but some
tests were comparing it with the raw values read from cat-file output
for a commit object, and it was really painful.

^ permalink raw reply

* Re: [PATCH 10/13] contrib/subtree: Code cleaning and refactoring
From: Junio C Hamano @ 2013-02-05  5:01 UTC (permalink / raw)
  To: David A. Greene
  Cc: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani,
	"David A. Greene <greened
In-Reply-To: <1360037173-23291-11-git-send-email-greened@obbligato.org>

"David A. Greene" <greened@obbligato.org> writes:

> From: Techlive Zheng <techlivezheng@gmail.com>
>
> Mostly prepare for the later tests refactoring.
>
> Signed-off-by: Techlive Zheng <techlivezheng@gmail.com>
> Signed-off-by: David A. Greene <greened@obbligato.org>
> ---
>  contrib/subtree/t/t7900-subtree.sh |  270 ++++++++++++++++++------------------
>  1 file changed, 136 insertions(+), 134 deletions(-)
>
> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
> index e6bcd50..9cfaaf9 100755
> --- a/contrib/subtree/t/t7900-subtree.sh
> +++ b/contrib/subtree/t/t7900-subtree.sh
> @@ -4,7 +4,7 @@
>  #
>  test_description='Basic porcelain support for subtrees
>  
> -This test verifies the basic operation of the merge, pull, add
> +This test verifies the basic operation of the add, pull, merge
>  and split subcommands of git subtree.
>  '
>  
> @@ -18,19 +18,6 @@ create()
>  	git add "$1"
>  }
>  
> -
> -check_equal()
> -{
> -	test_debug 'echo'
> -	test_debug "echo \"check a:\" \"{$1}\""
> -	test_debug "echo \"		 b:\" \"{$2}\""
> -	if [ "$1" = "$2" ]; then
> -		return 0
> -	else
> -		return 1
> -	fi
> -}
> -
>  fixnl()
>  {
>  	t=""
> @@ -55,6 +42,42 @@ undo()
>  	git reset --hard HEAD~
>  }
>  
> +test_equal()
> +{
> +	test_debug 'echo'
> +	test_debug "echo \"check a:\" \"{$1}\""
> +	test_debug "echo \"		 b:\" \"{$2}\""
> +	if [ "$1" = "$2" ]; then
> +		return 0
> +	else
> +		return 1
> +	fi
> +}

Why is the above improvement?  It does not seem to be fixing shell
script style to conform to the CodingGuidelines; the only thing I
can see it change is the name of the heper function.

Additional helper functions introduced by this patch seem to
introduce even more style violations.

This may be a tangent, but I would have expected "we expect these
two things to be the same, but help me debug the situation when then
differ" to be written more like this:

	test_equal () {
		if test "x$1" = "x$2"
		then
			return 0
		else
                	test_debug "echo" ...
                        return 1
		fi
	}

> +# Make sure no patch changes more than one file.
> +# The original set of commits changed only one file each.
> +# A multi-file change would imply that we pruned commits
> +# too aggressively.
> +join_commits()
> +{
> +	commit=
> +	all=
> +	while read x y; do
> +		if [ -z "$x" ]; then
> +			continue
> +		elif [ "$x" = "commit:" ]; then
> +			if [ -n "$commit" ]; then
> +				echo "$commit $all"
> +				all=
> +			fi
> +			commit="$y"
> +		else
> +			all="$all $y"
> +		fi
> +	done
> +	echo "$commit $all"
> +}

Swapped location in the file and renamed the function?  Doing
anything else?

This only reads from 

    git log --pretty="format:commit: %H"

so I am not sure how $all is ever relevant.

Doesn't it always see "$x=commit:" with "$y=<commit object name>"?

>  last_commit_message()
>  {
>  	git log --pretty=format:%s -1
> @@ -97,7 +120,7 @@ test_expect_success 'add main4' '
>  		create main4 &&
>  		git commit -m "main4" &&
>  		git branch -m master mainline &&
> -		git branch subdir
> +		git branch init
>  '
>  
>  test_expect_success 'fetch subproj history' '
> @@ -105,40 +128,43 @@ test_expect_success 'fetch subproj history' '
>  		git branch sub1 FETCH_HEAD
>  '
>  
> -test_expect_success 'no subtree exists in main tree' '
> -		test_must_fail git subtree merge --prefix=subdir sub1
> -'
> -
>  test_expect_success 'no pull from non-existant subtree' '
>  		test_must_fail git subtree pull --prefix=subdir ./subproj sub1
>  '
>  
v> -test_expect_success 'check if --message works for add' '
> -		git subtree add --prefix=subdir --message="Added subproject" sub1 &&
> -		check_equal ''"$(last_commit_message)"'' "Added subproject" &&
> +test_expect_success 'no merge from non-existant subtree' '

s/tant/tent/

The remainder of the patch not snipped for others.

> +		test_must_fail git subtree merge --prefix=subdir FETCH_HEAD
> +'
> +
> +test_expect_success 'add subproj as subtree into subdir/ with --prefix' '
> +		git subtree add --prefix=subdir FETCH_HEAD &&
> +		test_equal "$(last_commit_message)" "Add '\''subdir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" &&
>  		undo
>  '
>  
> -test_expect_success 'check if --message works as -m and --prefix as -P' '
> -		git subtree add -P subdir -m "Added subproject using git subtree" sub1 &&
> -		check_equal ''"$(last_commit_message)"'' "Added subproject using git subtree" &&
> +test_expect_success 'add subproj as subtree into subdir/ with --prefix and --message' '
> +		git subtree add --prefix=subdir --message="Added subproject" FETCH_HEAD &&
> +		test_equal "$(last_commit_message)" "Added subproject" &&
>  		undo
>  '
>  
> -test_expect_success 'check if --message works with squash too' '
> -		git subtree add -P subdir -m "Added subproject with squash" --squash sub1 &&
> -		check_equal ''"$(last_commit_message)"'' "Added subproject with squash" &&
> +test_expect_success 'add subproj as subtree into subdir/ with --prefix as -P and --message as -m' '
> +		git subtree add -P subdir -m "Added subproject" FETCH_HEAD &&
> +		test_equal "$(last_commit_message)" "Added subproject" &&
>  		undo
>  '
>  
> -test_expect_success 'add subproj to mainline' '
> -		git subtree add --prefix=subdir/ FETCH_HEAD &&
> -		check_equal ''"$(last_commit_message)"'' "Add '"'subdir/'"' from commit '"'"'''"$(git rev-parse sub1)"'''"'"'"
> +test_expect_success 'add subproj as subtree into subdir/ with --squash and --prefix and --message' '
> +		git subtree add --prefix=subdir --message="Added subproject with squash" --squash FETCH_HEAD &&
> +		test_equal "$(last_commit_message)" "Added subproject with squash" &&
> +		undo
>  '
>  
> -# this shouldn't actually do anything, since FETCH_HEAD is already a parent
> -test_expect_success 'merge fetched subproj' '
> -		git merge -m "merge -s -ours" -s ours FETCH_HEAD
> +test_expect_success 'merge the added subproj again, should do nothing' '
> +		git subtree add --prefix=subdir FETCH_HEAD &&
> +		# this shouldn not actually do anything, since FETCH_HEAD
> +		# is already a parent
> +		git merge -s ours -m "merge -s -ours" FETCH_HEAD
>  '
>  
>  test_expect_success 'add main-sub5' '
> @@ -161,25 +187,30 @@ test_expect_success 'fetch new subproj history' '
>  		git branch sub2 FETCH_HEAD
>  '
>  
> -test_expect_success 'check if --message works for merge' '
> -		git subtree merge --prefix=subdir -m "Merged changes from subproject" sub2 &&
> -		check_equal ''"$(last_commit_message)"'' "Merged changes from subproject" &&
> +test_expect_success 'merge new subproj history into subdir/ with --prefix' '
> +		git subtree merge --prefix=subdir FETCH_HEAD &&
> +		test_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into mainline" &&
>  		undo
>  '
>  
> -test_expect_success 'check if --message for merge works with squash too' '
> -		git subtree merge --prefix subdir -m "Merged changes from subproject using squash" --squash sub2 &&
> -		check_equal ''"$(last_commit_message)"'' "Merged changes from subproject using squash" &&
> +test_expect_success 'merge new subproj history into subdir/ with --prefix and --message' '
> +		git subtree merge --prefix=subdir --message="Merged changes from subproject" FETCH_HEAD &&
> +		test_equal "$(last_commit_message)" "Merged changes from subproject" &&
>  		undo
>  '
>  
> -test_expect_success 'merge new subproj history into subdir' '
> +test_expect_success 'merge new subproj history into subdir/ with --squash and --prefix and --message' '
> +		git subtree merge --prefix=subdir --message="Merged changes from subproject using squash" --squash FETCH_HEAD &&
> +		test_equal "$(last_commit_message)" "Merged changes from subproject using squash" &&
> +		undo
> +'
> +
> +test_expect_success 'merge new subproj history into subdir/' '
>  		git subtree merge --prefix=subdir FETCH_HEAD &&
> -		git branch pre-split &&
> -		check_equal ''"$(last_commit_message)"'' "Merge commit '"'"'"$(git rev-parse sub2)"'"'"' into mainline"
> +		git branch pre-split
>  '
>  
> -test_expect_success 'Check that prefix argument is required for split' '
> +test_expect_success 'split requires option --prefix' '
>  		echo "You must provide the --prefix option." > expected &&
>  		test_must_fail git subtree split > actual 2>&1 &&
>  		test_debug "echo -n expected: " &&
> @@ -190,59 +221,56 @@ test_expect_success 'Check that prefix argument is required for split' '
>  		rm -f expected actual
>  '
>  
> -test_expect_success 'Check that the <prefix> exists for a split' '
> -		echo "'"'"'non-existent-directory'"'"'" does not exist\; use "'"'"'git subtree add'"'"'" > expected &&
> +test_expect_success 'split requires path given by option --prefix must exist' '
> +		echo "'\''non-existent-directory'\'' does not exist; use '\''git subtree add'\''" > expected &&
>  		test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&
>  		test_debug "echo -n expected: " &&
>  		test_debug "cat expected" &&
>  		test_debug "echo -n actual: " &&
>  		test_debug "cat actual" &&
> -		test_cmp expected actual
> -#		 rm -f expected actual
> +		test_cmp expected actual &&
> +		rm -f expected actual
>  '
>  
> -test_expect_success 'check if --message works for split+rejoin' '
> -		spl1=''"$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
> -		git branch spl1 "$spl1" &&
> -		check_equal ''"$(last_commit_message)"'' "Split & rejoin" &&
> -		undo
> -'
> +test_expect_success 'split subdir/ with --rejoin' '
> +		spl1=$(git subtree split --prefix=subdir --annotate="*") &&
> + 		git branch spl1 "$spl1" &&
> +		git subtree split --prefix=subdir --annotate="*" --rejoin &&
> +		test_equal "$(last_commit_message)" "Split '\''subdir/'\'' into commit '\''$spl1'\''" &&
> + 		undo
> + '
>  
> -test_expect_success 'check split with --branch' '
> -		spl1=$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin) &&
> -		undo &&
> -		git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --branch splitbr1 &&
> -		check_equal ''"$(git rev-parse splitbr1)"'' "$spl1"
> +test_expect_success 'split subdir/ with --rejoin and --message' '
> +		git subtree split --prefix=subdir --message="Split & rejoin" --annotate="*" --rejoin &&
> +		test_equal "$(last_commit_message)" "Split & rejoin" &&
> +		undo
>  '
>  
> -test_expect_success 'check hash of split' '
> -        spl1=$(git subtree split --prefix subdir) &&
> -        undo &&
> -        git subtree split --prefix subdir --branch splitbr1test &&
> -        check_equal ''"$(git rev-parse splitbr1test)"'' "$spl1"
> -        git checkout splitbr1test &&
> -        new_hash=$(git rev-parse HEAD~2) &&
> -        git checkout mainline &&
> -        check_equal ''"$new_hash"'' "$subdir_hash"
> -'
> +test_expect_success 'split subdir/ with --branch' '
> +		spl1=$(git subtree split --prefix=subdir --message="Split & rejoin" --annotate="*" --rejoin) &&
> + 		undo &&
> +		git subtree split --prefix=subdir --annotate="*" --branch splitbr1 &&
> +		test_equal "$(git rev-parse splitbr1)" "$spl1"
> + '
>  
> -test_expect_success 'check split with --branch for an existing branch' '
> -		spl1=''"$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
> +test_expect_success 'split subdir/ with --branch for an existing branch' '
> +		spl1=$(git subtree split --prefix=subdir --annotate="*" --message="Split & rejoin" --rejoin) &&
>  		undo &&
>  		git branch splitbr2 sub1 &&
> -		git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --branch splitbr2 &&
> -		check_equal ''"$(git rev-parse splitbr2)"'' "$spl1"
> +		git subtree split --prefix=subdir --annotate="*" --branch splitbr2 &&
> +		test_equal "$(git rev-parse splitbr2)" "$spl1"
>  '
>  
> -test_expect_success 'check split with --branch for an incompatible branch' '
> -		test_must_fail git subtree split --prefix subdir --onto FETCH_HEAD --branch subdir
> +test_expect_success 'split subdir/ with --branch for an incompatible branch' '
> +		test_must_fail git subtree split --prefix=subdir --branch init
>  '
>  
> -test_expect_success 'check split+rejoin' '
> -		spl1=''"$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
> +test_expect_success 'check --unannotate' '
> +		spl1=$(git subtree split --unannotate="subproj:" --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin) &&
>  		undo &&
> -		git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --rejoin &&
> -		check_equal ''"$(last_commit_message)"'' "Split '"'"'subdir/'"'"' into commit '"'"'"$spl1"'"'"'"
> + 		git subtree split --unannotate="subproj:" --prefix subdir --onto FETCH_HEAD --branch splitunann &&
> +		test_equal "$(git rev-parse splitunann)" "$spl1" &&
> +		test_equal "$(git log splitunann | grep subproj)" ""
>  '
>  
>  test_expect_success 'add main-sub8' '
> @@ -268,8 +296,8 @@ test_expect_success 'add sub9' '
>  cd ..
>  
>  test_expect_success 'split for sub8' '
> -		split2=''"$(git subtree split --annotate='"'*'"' --prefix subdir/ --rejoin)"''
> -		git branch split2 "$split2"
> +		spl2=$(git subtree split --prefix=subdir/ --annotate="*" --rejoin) &&
> +		git branch spl2 "$spl2"
>  '
>  
>  test_expect_success 'add main-sub10' '
> @@ -278,7 +306,7 @@ test_expect_success 'add main-sub10' '
>  '
>  
>  test_expect_success 'split for sub10' '
> -		spl3=''"$(git subtree split --annotate='"'*'"' --prefix subdir --rejoin)"'' &&
> +		spl3=$(git subtree split --prefix=subdir --annotate="*" --rejoin) &&
>  		git branch spl3 "$spl3"
>  '
>  
> @@ -299,13 +327,13 @@ chks="sub1 sub2 sub3 sub9"
>  chks_sub=$(echo $chks | multiline | sed 's,^,subdir/,' | fixnl)
>  
>  test_expect_success 'make sure exactly the right set of files ends up in the subproj' '
> -		subfiles=''"$(git ls-files | fixnl)"'' &&
> -		check_equal "$subfiles" "$chkms $chks"
> +		subfiles=$(git ls-files | fixnl) &&
> +		test_equal "$subfiles" "$chkms $chks"
>  '
>  
> -test_expect_success 'make sure the subproj history *only* contains commits that affect the subdir' '
> -		allchanges=''"$(git log --name-only --pretty=format:'"''"' | sort | fixnl)"'' &&
> -		check_equal "$allchanges" "$chkms $chks"
> +test_expect_success 'make sure the subproj *only* contains commits that affect the subdir' '
> +		allchanges=$(git log --name-only --pretty=format:"" | sort | fixnl) &&
> +		test_equal "$allchanges" "$chkms $chks"
>  '
>  
>  # Back to mainline
> @@ -318,25 +346,25 @@ test_expect_success 'pull from subproj' '
>  '
>  
>  test_expect_success 'make sure exactly the right set of files ends up in the mainline' '
> -		mainfiles=''"$(git ls-files | fixnl)"'' &&
> -		check_equal "$mainfiles" "$chkm $chkms_sub $chks_sub"
> +		mainfiles=$(git ls-files | fixnl) &&
> +		test_equal "$mainfiles" "$chkm $chkms_sub $chks_sub"
>  '
>  
>  test_expect_success 'make sure each filename changed exactly once in the entire history' '
>  		# main-sub?? and /subdir/main-sub?? both change, because those are the
>  		# changes that were split into their own history.  And subdir/sub?? never
>  		# change, since they were *only* changed in the subtree branch.
> -		allchanges=''"$(git log --name-only --pretty=format:'"''"' | sort | fixnl)"'' &&
> -		check_equal "$allchanges" ''"$(echo $chkms $chkm $chks $chkms_sub | multiline | sort | fixnl)"''
> +		allchanges=$(git log --name-only --pretty=format:"" | sort | fixnl) &&
> +		test_equal "$allchanges" "$(echo $chkms $chkm $chks $chkms_sub | multiline | sort | fixnl)"
>  '
>  
>  test_expect_success 'make sure the --rejoin commits never make it into subproj' '
> -		check_equal ''"$(git log --pretty=format:'"'%s'"' HEAD^2 | grep -i split)"'' ""
> +		test_equal "$(git log --pretty=format:"%s" HEAD^2 | grep -i split)" ""
>  '
>  
>  test_expect_success 'make sure no "git subtree" tagged commits make it into subproj' '
>  		# They are meaningless to subproj since one side of the merge refers to the mainline
> -		check_equal ''"$(git log --pretty=format:'"'%s%n%b'"' HEAD^2 | grep "git-subtree.*:")"'' ""
> +		test_equal "$(git log --pretty=format:"%s%n%b" HEAD^2 | grep "git-subtree.*:")" ""
>  '
>  
>  # prepare second pair of repositories
> @@ -374,7 +402,7 @@ cd ../main
>  test_expect_success 'add sub as subdir in main' '
>  		git fetch ../sub master &&
>  		git branch sub2 FETCH_HEAD &&
> -		git subtree add --prefix subdir sub2
> +		git subtree add --prefix=subdir sub2
>  '
>  
>  cd ../sub
> @@ -389,7 +417,7 @@ cd ../main
>  test_expect_success 'merge from sub' '
>  		git fetch ../sub master &&
>  		git branch sub3 FETCH_HEAD &&
> -		git subtree merge --prefix subdir sub3
> +		git subtree merge --prefix=subdir sub3
>  '
>  
>  test_expect_success 'add main-sub4' '
> @@ -398,7 +426,7 @@ test_expect_success 'add main-sub4' '
>  '
>  
>  test_expect_success 'split for main-sub4 without --onto' '
> -		git subtree split --prefix subdir --branch mainsub4
> +		git subtree split --prefix=subdir --branch mainsub4
>  '
>  
>  # at this point, the new commit parent should be sub3 if it is not,
> @@ -407,7 +435,7 @@ test_expect_success 'split for main-sub4 without --onto' '
>  # itself)
>  
>  test_expect_success 'check that the commit parent is sub3' '
> -		check_equal ''"$(git log --pretty=format:%P -1 mainsub4)"'' ''"$(git rev-parse sub3)"''
> +		test_equal "$(git log --pretty=format:%P -1 mainsub4)" "$(git rev-parse sub3)"
>  '
>  
>  test_expect_success 'add main-sub5' '
> @@ -420,49 +448,23 @@ test_expect_success 'split for main-sub5 without --onto' '
>  		# also test that we still can split out an entirely new subtree
>  		# if the parent of the first commit in the tree is not empty,
>  		# then the new subtree has accidently been attached to something
> -		git subtree split --prefix subdir2 --branch mainsub5 &&
> -		check_equal ''"$(git log --pretty=format:%P -1 mainsub5)"'' ""
> +		git subtree split --prefix=subdir2 --branch mainsub5 &&
> +		test_equal "$(git log --pretty=format:%P -1 mainsub5)" ""
>  '
>  
> -# make sure no patch changes more than one file.  The original set of commits
> -# changed only one file each.  A multi-file change would imply that we pruned
> -# commits too aggressively.
> -joincommits()
> -{
> -	commit=
> -	all=
> -	while read x y; do
> -		#echo "{$x}" >&2
> -		if [ -z "$x" ]; then
> -			continue
> -		elif [ "$x" = "commit:" ]; then
> -			if [ -n "$commit" ]; then
> -				echo "$commit $all"
> -				all=
> -			fi
> -			commit="$y"
> -		else
> -			all="$all $y"
> -		fi
> -	done
> -	echo "$commit $all"
> -}
> -
>  test_expect_success 'verify one file change per commit' '
>  		x= &&
> -		list=''"$(git log --pretty=format:'"'commit: %H'"' | joincommits)"'' &&
> -#		 test_debug "echo HERE" &&
> -#		 test_debug "echo ''"$list"''" &&
> -		(git log --pretty=format:'"'commit: %H'"' | joincommits |
> -		(		while read commit a b; do
> -				test_debug "echo Verifying commit "''"$commit"''
> -				test_debug "echo a: "''"$a"''
> -				test_debug "echo b: "''"$b"''
> -				check_equal "$b" ""
> +		git log --pretty=format:"commit: %H" | join_commits |
> +		(
> +			while read commit a b; do
> +				test_debug "echo Verifying commit $commit"
> +				test_debug "echo a: $a"
> +				test_debug "echo b: $b"
> +				test_equal "$b" ""
>  				x=1
>  			done
> -			check_equal "$x" 1
> -		))
> +			test_equal "$x" 1
> +		)
>  '
>  
>  test_done

^ permalink raw reply

* Re: [PATCH 07/13] contrib/subtree: Fix whitespaces
From: Junio C Hamano @ 2013-02-05  4:42 UTC (permalink / raw)
  To: David A. Greene
  Cc: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani,
	"David A. Greene <greened
In-Reply-To: <1360037173-23291-8-git-send-email-greened@obbligato.org>

"David A. Greene" <greened@obbligato.org> writes:

> From: Techlive Zheng <techlivezheng@gmail.com>
>
> Previous code does not fulfill Git's whitespace policy.
>
> Signed-off-by: Techlive Zheng <techlivezheng@gmail.com>
> Signed-off-by: David A. Greene <greened@obbligato.org>
> ---

This does not seem to apply; I hand-tweaked it to make it apply, but
the reindentation of t/t7900 does not look correct.

> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
> index 3f17f55..e6a3702 100755
> --- a/contrib/subtree/t/t7900-subtree.sh
> +++ b/contrib/subtree/t/t7900-subtree.sh
> @@ -23,7 +23,7 @@ check_equal()
>  {
>  	test_debug 'echo'
>  	test_debug "echo \"check a:\" \"{$1}\""
> -	test_debug "echo \"      b:\" \"{$2}\""
> +	test_debug "echo \"		 b:\" \"{$2}\""
>  	if [ "$1" = "$2" ]; then
>  		return 0
>  	else
> @@ -61,17 +61,17 @@ last_commit_message()
>  }
>  
>  test_expect_success 'init subproj' '
> -        test_create_repo subproj
> +		test_create_repo subproj

Perhaps this was originally done with an editor whose tabwidth was
set to 4?  It gives too much indentation when standard tabwidth of 8
is used.

^ permalink raw reply

* Re: [PATCH 01/13] contrib/subtree: Remove Test Number Comments
From: Junio C Hamano @ 2013-02-05  4:39 UTC (permalink / raw)
  To: David A. Greene
  Cc: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani,
	"David A. Greene <greened
In-Reply-To: <1360037173-23291-2-git-send-email-greened@obbligato.org>

Thanks.

This is minor but I'd prefer to see that Subject lines Not To Do
Title Case (please see "git log --oneline --no-merges -20 master"
and imitate them for uniformity).

I'll tweak them while queuing so this alone is not a reason for
having to resend.

Thanks.

^ permalink raw reply

* [PATCH 11/13] contrib/subtree: Make each test self-contained
From: David A. Greene @ 2013-02-05  4:06 UTC (permalink / raw)
  To: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani
  Cc: David A. Greene
In-Reply-To: <1360037173-23291-1-git-send-email-greened@obbligato.org>

From: Techlive Zheng <techlivezheng@gmail.com>

Signed-off-by: Techlive Zheng <techlivezheng@gmail.com>
Signed-off-by: David A. Greene <greened@obbligato.org>
---
 contrib/subtree/t/t7900-subtree.sh |  871 +++++++++++++++++++++++++-----------
 1 file changed, 613 insertions(+), 258 deletions(-)

diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index 9cfaaf9..769b116 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -12,12 +12,6 @@ export TEST_DIRECTORY=$(pwd)/../../../t
 
 . ../../../t/test-lib.sh
 
-create()
-{
-	echo "$1" >"$1"
-	git add "$1"
-}
-
 fixnl()
 {
 	t=""
@@ -37,11 +31,6 @@ multiline()
 	done
 }
 
-undo()
-{
-	git reset --hard HEAD~
-}
-
 test_equal()
 {
 	test_debug 'echo'
@@ -78,381 +67,746 @@ join_commits()
 	echo "$commit $all"
 }
 
+test_create_commit() (
+	repo=$1
+	commit=$2
+	cd "$repo"
+	mkdir -p "$(dirname "$commit")"
+	echo "$commit" > "$commit"
+	git add "$commit"
+	git commit -m "$commit"
+)
+
 last_commit_message()
 {
 	git log --pretty=format:%s -1
 }
 
-test_expect_success 'init subproj' '
-		test_create_repo subproj
-'
-
-# To the subproject!
-cd subproj
-
-test_expect_success 'add sub1' '
-		create sub1 &&
-		git commit -m "sub1" &&
-		git branch sub1 &&
-		git branch -m master subproj
-'
-
-# Save this hash for testing later.
-
-subdir_hash=`git rev-parse HEAD`
-
-test_expect_success 'add sub2' '
-		create sub2 &&
-		git commit -m "sub2" &&
-		git branch sub2
-'
-
-test_expect_success 'add sub3' '
-		create sub3 &&
-		git commit -m "sub3" &&
-		git branch sub3
-'
-
-# Back to mainline
-cd ..
-
-test_expect_success 'add main4' '
-		create main4 &&
-		git commit -m "main4" &&
-		git branch -m master mainline &&
-		git branch init
-'
+#
+# Tests for 'git subtree add'
+#
 
-test_expect_success 'fetch subproj history' '
-		git fetch ./subproj sub1 &&
-		git branch sub1 FETCH_HEAD
-'
 
 test_expect_success 'no pull from non-existant subtree' '
-		test_must_fail git subtree pull --prefix=subdir ./subproj sub1
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		test_must_fail git subtree pull --prefix=subdir ./subproj master
+	)
 '
 
 test_expect_success 'no merge from non-existant subtree' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		test_must_fail git subtree merge --prefix=subdir FETCH_HEAD
+	)
 '
 
 test_expect_success 'add subproj as subtree into subdir/ with --prefix' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree add --prefix=subdir FETCH_HEAD &&
-		test_equal "$(last_commit_message)" "Add '\''subdir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" &&
-		undo
+		test_equal "$(last_commit_message)" "Add '\''subdir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''"
+	)
 '
 
 test_expect_success 'add subproj as subtree into subdir/ with --prefix and --message' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree add --prefix=subdir --message="Added subproject" FETCH_HEAD &&
-		test_equal "$(last_commit_message)" "Added subproject" &&
-		undo
+		test_equal "$(last_commit_message)" "Added subproject"
+	)
 '
 
 test_expect_success 'add subproj as subtree into subdir/ with --prefix as -P and --message as -m' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree add -P subdir -m "Added subproject" FETCH_HEAD &&
-		test_equal "$(last_commit_message)" "Added subproject" &&
-		undo
+		test_equal "$(last_commit_message)" "Added subproject"
+	)
 '
 
 test_expect_success 'add subproj as subtree into subdir/ with --squash and --prefix and --message' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree add --prefix=subdir --message="Added subproject with squash" --squash FETCH_HEAD &&
-		test_equal "$(last_commit_message)" "Added subproject with squash" &&
-		undo
+		test_equal "$(last_commit_message)" "Added subproject with squash"
+	)
 '
 
 test_expect_success 'merge the added subproj again, should do nothing' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree add --prefix=subdir FETCH_HEAD &&
 		# this shouldn not actually do anything, since FETCH_HEAD
 		# is already a parent
 		git merge -s ours -m "merge -s -ours" FETCH_HEAD
+	)
 '
 
-test_expect_success 'add main-sub5' '
-		create subdir/main-sub5 &&
-		git commit -m "subproj: main-sub5"
-'
-
-test_expect_success 'add main6' '
-		create main6 &&
-		git commit -m "main6 boring"
-'
-
-test_expect_success 'add main-sub7' '
-		create subdir/main-sub7 &&
-		git commit -m "subproj: main-sub7"
-'
-
-test_expect_success 'fetch new subproj history' '
-		git fetch ./subproj sub2 &&
-		git branch sub2 FETCH_HEAD
-'
+#
+# Tests for 'git subtree merge'
+#
 
 test_expect_success 'merge new subproj history into subdir/ with --prefix' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		test_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into mainline" &&
-		undo
+		test_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+	)
 '
 
 test_expect_success 'merge new subproj history into subdir/ with --prefix and --message' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir --message="Merged changes from subproject" FETCH_HEAD &&
-		test_equal "$(last_commit_message)" "Merged changes from subproject" &&
-		undo
+		test_equal "$(last_commit_message)" "Merged changes from subproject"
+	)
 '
 
 test_expect_success 'merge new subproj history into subdir/ with --squash and --prefix and --message' '
+	test_create_repo "$test_count/subproj" &&
+	test_create_repo "$test_count" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir --message="Merged changes from subproject using squash" --squash FETCH_HEAD &&
-		test_equal "$(last_commit_message)" "Merged changes from subproject using squash" &&
-		undo
+		test_equal "$(last_commit_message)" "Merged changes from subproject using squash"
+	)
 '
 
-test_expect_success 'merge new subproj history into subdir/' '
-		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git branch pre-split
-'
+#
+# Tests for 'git subtree split'
+#
 
 test_expect_success 'split requires option --prefix' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD &&
 		echo "You must provide the --prefix option." > expected &&
 		test_must_fail git subtree split > actual 2>&1 &&
 		test_debug "echo -n expected: " &&
 		test_debug "cat expected" &&
 		test_debug "echo -n actual: " &&
 		test_debug "cat actual" &&
-		test_cmp expected actual &&
-		rm -f expected actual
+		test_cmp expected actual
+	)
 '
 
 test_expect_success 'split requires path given by option --prefix must exist' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD &&
 		echo "'\''non-existent-directory'\'' does not exist; use '\''git subtree add'\''" > expected &&
 		test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&
 		test_debug "echo -n expected: " &&
 		test_debug "cat expected" &&
 		test_debug "echo -n actual: " &&
 		test_debug "cat actual" &&
-		test_cmp expected actual &&
-		rm -f expected actual
+		test_cmp expected actual
+	)
 '
 
 test_expect_success 'split subdir/ with --rejoin' '
-		spl1=$(git subtree split --prefix=subdir --annotate="*") &&
- 		git branch spl1 "$spl1" &&
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		split_hash=$(git subtree split --prefix=subdir --annotate="*") &&
 		git subtree split --prefix=subdir --annotate="*" --rejoin &&
-		test_equal "$(last_commit_message)" "Split '\''subdir/'\'' into commit '\''$spl1'\''" &&
- 		undo
+		test_equal "$(last_commit_message)" "Split '\''subdir/'\'' into commit '\''$split_hash'\''"
+	)
  '
 
 test_expect_success 'split subdir/ with --rejoin and --message' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
 		git subtree split --prefix=subdir --message="Split & rejoin" --annotate="*" --rejoin &&
-		test_equal "$(last_commit_message)" "Split & rejoin" &&
-		undo
+		test_equal "$(last_commit_message)" "Split & rejoin"
+	)
 '
 
 test_expect_success 'split subdir/ with --branch' '
-		spl1=$(git subtree split --prefix=subdir --message="Split & rejoin" --annotate="*" --rejoin) &&
- 		undo &&
-		git subtree split --prefix=subdir --annotate="*" --branch splitbr1 &&
-		test_equal "$(git rev-parse splitbr1)" "$spl1"
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		split_hash=$(git subtree split --prefix=subdir --annotate="*") &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br &&
+		test_equal "$(git rev-parse subproj-br)" "$split_hash"
+	)
  '
 
 test_expect_success 'split subdir/ with --branch for an existing branch' '
-		spl1=$(git subtree split --prefix=subdir --annotate="*" --message="Split & rejoin" --rejoin) &&
-		undo &&
-		git branch splitbr2 sub1 &&
-		git subtree split --prefix=subdir --annotate="*" --branch splitbr2 &&
-		test_equal "$(git rev-parse splitbr2)" "$spl1"
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git branch subproj-br FETCH_HEAD &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		split_hash=$(git subtree split --prefix=subdir --annotate="*") &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br &&
+		test_equal "$(git rev-parse subproj-br)" "$split_hash"
+	)
 '
 
 test_expect_success 'split subdir/ with --branch for an incompatible branch' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git branch init HEAD &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
 		test_must_fail git subtree split --prefix=subdir --branch init
+	)
 '
 
-test_expect_success 'check --unannotate' '
-		spl1=$(git subtree split --unannotate="subproj:" --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin) &&
-		undo &&
- 		git subtree split --unannotate="subproj:" --prefix subdir --onto FETCH_HEAD --branch splitunann &&
-		test_equal "$(git rev-parse splitunann)" "$spl1" &&
-		test_equal "$(git log splitunann | grep subproj)" ""
-'
-
-test_expect_success 'add main-sub8' '
-		create subdir/main-sub8 &&
-		git commit -m "main-sub8"
-'
-
-# To the subproject!
-cd ./subproj
-
-test_expect_success 'merge split into subproj' '
-		git fetch .. spl1 &&
-		git branch spl1 FETCH_HEAD &&
-		git merge FETCH_HEAD
-'
-
-test_expect_success 'add sub9' '
-		create sub9 &&
-		git commit -m "sub9"
-'
-
-# Back to mainline
-cd ..
-
-test_expect_success 'split for sub8' '
-		spl2=$(git subtree split --prefix=subdir/ --annotate="*" --rejoin) &&
-		git branch spl2 "$spl2"
-'
-
-test_expect_success 'add main-sub10' '
-		create subdir/main-sub10 &&
-		git commit -m "main-sub10"
-'
-
-test_expect_success 'split for sub10' '
-		spl3=$(git subtree split --prefix=subdir --annotate="*" --rejoin) &&
-		git branch spl3 "$spl3"
-'
-
-# To the subproject!
-cd ./subproj
-
-test_expect_success 'merge split into subproj' '
-		git fetch .. spl3 &&
-		git branch spl3 FETCH_HEAD &&
-		git merge FETCH_HEAD &&
-		git branch subproj-merge-spl3
-'
-
-chkm="main4 main6"
-chkms="main-sub10 main-sub5 main-sub7 main-sub8"
-chkms_sub=$(echo $chkms | multiline | sed 's,^,subdir/,' | fixnl)
-chks="sub1 sub2 sub3 sub9"
-chks_sub=$(echo $chks | multiline | sed 's,^,subdir/,' | fixnl)
+#
+# Validity checking
+#
 
 test_expect_success 'make sure exactly the right set of files ends up in the subproj' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count/subproj" sub3 &&
+	test_create_commit "$test_count" subdir/main-sub3 &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count" subdir/main-sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD &&
+
+		chks="sub1 sub2 sub3 sub4" &&
+		chks_sub=$(echo $chks | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
+		chkms="main-sub1 main-sub2 main-sub3 main-sub4" &&
+		chkms_sub=$(echo $chkms | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
+
 		subfiles=$(git ls-files | fixnl) &&
 		test_equal "$subfiles" "$chkms $chks"
+	)
 '
 
 test_expect_success 'make sure the subproj *only* contains commits that affect the subdir' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count/subproj" sub3 &&
+	test_create_commit "$test_count" subdir/main-sub3 &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count" subdir/main-sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD &&
+
+		chks="sub1 sub2 sub3 sub4" &&
+		chks_sub=$(echo $chks | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
+		chkms="main-sub1 main-sub2 main-sub3 main-sub4" &&
+		chkms_sub=$(echo $chkms | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
+
 		allchanges=$(git log --name-only --pretty=format:"" | sort | fixnl) &&
 		test_equal "$allchanges" "$chkms $chks"
-'
-
-# Back to mainline
-cd ..
-
-test_expect_success 'pull from subproj' '
-		git fetch ./subproj subproj-merge-spl3 &&
-		git branch subproj-merge-spl3 FETCH_HEAD &&
-		git subtree pull --prefix=subdir ./subproj subproj-merge-spl3
+	)
 '
 
 test_expect_success 'make sure exactly the right set of files ends up in the mainline' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count/subproj" sub3 &&
+	test_create_commit "$test_count" subdir/main-sub3 &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count" subdir/main-sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	(
+		cd "$test_count" &&
+		git subtree pull --prefix=subdir ./subproj master &&
+
+		chkm="main1 main2" &&
+		chks="sub1 sub2 sub3 sub4" &&
+		chks_sub=$(echo $chks | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
+		chkms="main-sub1 main-sub2 main-sub3 main-sub4" &&
+		chkms_sub=$(echo $chkms | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
 		mainfiles=$(git ls-files | fixnl) &&
 		test_equal "$mainfiles" "$chkm $chkms_sub $chks_sub"
+	)
 '
 
 test_expect_success 'make sure each filename changed exactly once in the entire history' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count/subproj" sub3 &&
+	test_create_commit "$test_count" subdir/main-sub3 &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count" subdir/main-sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	(
+		cd "$test_count" &&
+		git subtree pull --prefix=subdir ./subproj master &&
+
+		chkm="main1 main2" &&
+		chks="sub1 sub2 sub3 sub4" &&
+		chks_sub=$(echo $chks | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
+		chkms="main-sub1 main-sub2 main-sub3 main-sub4" &&
+		chkms_sub=$(echo $chkms | multiline | sed '\''s,^,subdir/,'\'' | fixnl) &&
+
 		# main-sub?? and /subdir/main-sub?? both change, because those are the
 		# changes that were split into their own history.  And subdir/sub?? never
 		# change, since they were *only* changed in the subtree branch.
 		allchanges=$(git log --name-only --pretty=format:"" | sort | fixnl) &&
 		test_equal "$allchanges" "$(echo $chkms $chkm $chks $chkms_sub | multiline | sort | fixnl)"
+	)
 '
 
 test_expect_success 'make sure the --rejoin commits never make it into subproj' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count/subproj" sub3 &&
+	test_create_commit "$test_count" subdir/main-sub3 &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count" subdir/main-sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	(
+		cd "$test_count" &&
+		git subtree pull --prefix=subdir ./subproj master &&
+
 		test_equal "$(git log --pretty=format:"%s" HEAD^2 | grep -i split)" ""
+	)
 '
 
 test_expect_success 'make sure no "git subtree" tagged commits make it into subproj' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	test_create_commit "$test_count" main2 &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	test_create_commit "$test_count" subdir/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count/subproj" sub3 &&
+	test_create_commit "$test_count" subdir/main-sub3 &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	test_create_commit "$test_count" subdir/main-sub4 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+	) &&
+	(
+		cd "$test_count/subproj" &&
+		git fetch .. subproj-br && git merge FETCH_HEAD
+	) &&
+	(
+		cd "$test_count" &&
+		git subtree pull --prefix=subdir ./subproj master &&
+
 		# They are meaningless to subproj since one side of the merge refers to the mainline
 		test_equal "$(git log --pretty=format:"%s%n%b" HEAD^2 | grep "git-subtree.*:")" ""
+	)
 '
 
-# prepare second pair of repositories
-mkdir test2
-cd test2
-
-test_expect_success 'init main' '
-		test_create_repo main
-'
-
-cd main
-
-test_expect_success 'add main1' '
-		create main1 &&
-		git commit -m "main1"
-'
-
-cd ..
-
-test_expect_success 'init sub' '
-		test_create_repo sub
-'
-
-cd sub
-
-test_expect_success 'add sub2' '
-		create sub2 &&
-		git commit -m "sub2"
-'
-
-cd ../main
-
-# check if split can find proper base without --onto
-
-test_expect_success 'add sub as subdir in main' '
-		git fetch ../sub master &&
-		git branch sub2 FETCH_HEAD &&
-		git subtree add --prefix=subdir sub2
-'
-
-cd ../sub
-
-test_expect_success 'add sub3' '
-		create sub3 &&
-		git commit -m "sub3"
-'
-
-cd ../main
-
-test_expect_success 'merge from sub' '
-		git fetch ../sub master &&
-		git branch sub3 FETCH_HEAD &&
-		git subtree merge --prefix=subdir sub3
-'
-
-test_expect_success 'add main-sub4' '
-		create subdir/main-sub4 &&
-		git commit -m "main-sub4"
-'
-
-test_expect_success 'split for main-sub4 without --onto' '
-		git subtree split --prefix=subdir --branch mainsub4
-'
-
-# at this point, the new commit parent should be sub3 if it is not,
-# something went wrong (the "newparent" of "master~" commit should
-# have been sub3, but it was not, because its cache was not set to
-# itself)
-
-test_expect_success 'check that the commit parent is sub3' '
-		test_equal "$(git log --pretty=format:%P -1 mainsub4)" "$(git rev-parse sub3)"
-'
+#
+# A new set of tests
+#
 
-test_expect_success 'add main-sub5' '
-		mkdir subdir2 &&
-		create subdir2/main-sub5 &&
-		git commit -m "main-sub5"
-'
+test_expect_success 'make sure "git subtree split" find the correct parent' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git branch subproj-ref FETCH_HEAD &&
+		git subtree merge --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --branch subproj-br &&
+
+		# at this point, the new commit parent should be subproj-ref, if it is
+		# not, something went wrong (the "newparent" of "master~" commit should
+		# have been sub2, but it was not, because its cache was not set to
+		# itself)
+		test_equal "$(git log --pretty=format:%P -1 subproj-br)" "$(git rev-parse subproj-ref)"
+	)
+'
+
+test_expect_success 'split a new subtree without --onto option' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --branch subproj-br
+	) &&
+	test_create_commit "$test_count" subdir2/main-sub2 &&
+	(
+		cd "$test_count" &&
 
-test_expect_success 'split for main-sub5 without --onto' '
 		# also test that we still can split out an entirely new subtree
 		# if the parent of the first commit in the tree is not empty,
 		# then the new subtree has accidently been attached to something
-		git subtree split --prefix=subdir2 --branch mainsub5 &&
-		test_equal "$(git log --pretty=format:%P -1 mainsub5)" ""
+		git subtree split --prefix=subdir2 --branch subproj2-br &&
+		test_equal "$(git log --pretty=format:%P -1 subproj2-br)" ""
+	)
 '
 
 test_expect_success 'verify one file change per commit' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git branch sub1 FETCH_HEAD &&
+		git subtree add --prefix=subdir sub1
+	) &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" subdir/main-sub1 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir --branch subproj-br
+	) &&
+	test_create_commit "$test_count" subdir2/main-sub2 &&
+	(
+		cd "$test_count" &&
+		git subtree split --prefix=subdir2 --branch subproj2-br &&
+
 		x= &&
 		git log --pretty=format:"commit: %H" | join_commits |
 		(
@@ -465,6 +819,7 @@ test_expect_success 'verify one file change per commit' '
 			done
 			test_equal "$x" 1
 		)
+	)
 '
 
 test_done
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 10/13] contrib/subtree: Code cleaning and refactoring
From: David A. Greene @ 2013-02-05  4:06 UTC (permalink / raw)
  To: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani
  Cc: David A. Greene
In-Reply-To: <1360037173-23291-1-git-send-email-greened@obbligato.org>

From: Techlive Zheng <techlivezheng@gmail.com>

Mostly prepare for the later tests refactoring.

Signed-off-by: Techlive Zheng <techlivezheng@gmail.com>
Signed-off-by: David A. Greene <greened@obbligato.org>
---
 contrib/subtree/t/t7900-subtree.sh |  270 ++++++++++++++++++------------------
 1 file changed, 136 insertions(+), 134 deletions(-)

diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index e6bcd50..9cfaaf9 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -4,7 +4,7 @@
 #
 test_description='Basic porcelain support for subtrees
 
-This test verifies the basic operation of the merge, pull, add
+This test verifies the basic operation of the add, pull, merge
 and split subcommands of git subtree.
 '
 
@@ -18,19 +18,6 @@ create()
 	git add "$1"
 }
 
-
-check_equal()
-{
-	test_debug 'echo'
-	test_debug "echo \"check a:\" \"{$1}\""
-	test_debug "echo \"		 b:\" \"{$2}\""
-	if [ "$1" = "$2" ]; then
-		return 0
-	else
-		return 1
-	fi
-}
-
 fixnl()
 {
 	t=""
@@ -55,6 +42,42 @@ undo()
 	git reset --hard HEAD~
 }
 
+test_equal()
+{
+	test_debug 'echo'
+	test_debug "echo \"check a:\" \"{$1}\""
+	test_debug "echo \"		 b:\" \"{$2}\""
+	if [ "$1" = "$2" ]; then
+		return 0
+	else
+		return 1
+	fi
+}
+
+# Make sure no patch changes more than one file.
+# The original set of commits changed only one file each.
+# A multi-file change would imply that we pruned commits
+# too aggressively.
+join_commits()
+{
+	commit=
+	all=
+	while read x y; do
+		if [ -z "$x" ]; then
+			continue
+		elif [ "$x" = "commit:" ]; then
+			if [ -n "$commit" ]; then
+				echo "$commit $all"
+				all=
+			fi
+			commit="$y"
+		else
+			all="$all $y"
+		fi
+	done
+	echo "$commit $all"
+}
+
 last_commit_message()
 {
 	git log --pretty=format:%s -1
@@ -97,7 +120,7 @@ test_expect_success 'add main4' '
 		create main4 &&
 		git commit -m "main4" &&
 		git branch -m master mainline &&
-		git branch subdir
+		git branch init
 '
 
 test_expect_success 'fetch subproj history' '
@@ -105,40 +128,43 @@ test_expect_success 'fetch subproj history' '
 		git branch sub1 FETCH_HEAD
 '
 
-test_expect_success 'no subtree exists in main tree' '
-		test_must_fail git subtree merge --prefix=subdir sub1
-'
-
 test_expect_success 'no pull from non-existant subtree' '
 		test_must_fail git subtree pull --prefix=subdir ./subproj sub1
 '
 
-test_expect_success 'check if --message works for add' '
-		git subtree add --prefix=subdir --message="Added subproject" sub1 &&
-		check_equal ''"$(last_commit_message)"'' "Added subproject" &&
+test_expect_success 'no merge from non-existant subtree' '
+		test_must_fail git subtree merge --prefix=subdir FETCH_HEAD
+'
+
+test_expect_success 'add subproj as subtree into subdir/ with --prefix' '
+		git subtree add --prefix=subdir FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Add '\''subdir/'\'' from commit '\''$(git rev-parse FETCH_HEAD)'\''" &&
 		undo
 '
 
-test_expect_success 'check if --message works as -m and --prefix as -P' '
-		git subtree add -P subdir -m "Added subproject using git subtree" sub1 &&
-		check_equal ''"$(last_commit_message)"'' "Added subproject using git subtree" &&
+test_expect_success 'add subproj as subtree into subdir/ with --prefix and --message' '
+		git subtree add --prefix=subdir --message="Added subproject" FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Added subproject" &&
 		undo
 '
 
-test_expect_success 'check if --message works with squash too' '
-		git subtree add -P subdir -m "Added subproject with squash" --squash sub1 &&
-		check_equal ''"$(last_commit_message)"'' "Added subproject with squash" &&
+test_expect_success 'add subproj as subtree into subdir/ with --prefix as -P and --message as -m' '
+		git subtree add -P subdir -m "Added subproject" FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Added subproject" &&
 		undo
 '
 
-test_expect_success 'add subproj to mainline' '
-		git subtree add --prefix=subdir/ FETCH_HEAD &&
-		check_equal ''"$(last_commit_message)"'' "Add '"'subdir/'"' from commit '"'"'''"$(git rev-parse sub1)"'''"'"'"
+test_expect_success 'add subproj as subtree into subdir/ with --squash and --prefix and --message' '
+		git subtree add --prefix=subdir --message="Added subproject with squash" --squash FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Added subproject with squash" &&
+		undo
 '
 
-# this shouldn't actually do anything, since FETCH_HEAD is already a parent
-test_expect_success 'merge fetched subproj' '
-		git merge -m "merge -s -ours" -s ours FETCH_HEAD
+test_expect_success 'merge the added subproj again, should do nothing' '
+		git subtree add --prefix=subdir FETCH_HEAD &&
+		# this shouldn not actually do anything, since FETCH_HEAD
+		# is already a parent
+		git merge -s ours -m "merge -s -ours" FETCH_HEAD
 '
 
 test_expect_success 'add main-sub5' '
@@ -161,25 +187,30 @@ test_expect_success 'fetch new subproj history' '
 		git branch sub2 FETCH_HEAD
 '
 
-test_expect_success 'check if --message works for merge' '
-		git subtree merge --prefix=subdir -m "Merged changes from subproject" sub2 &&
-		check_equal ''"$(last_commit_message)"'' "Merged changes from subproject" &&
+test_expect_success 'merge new subproj history into subdir/ with --prefix' '
+		git subtree merge --prefix=subdir FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\'' into mainline" &&
 		undo
 '
 
-test_expect_success 'check if --message for merge works with squash too' '
-		git subtree merge --prefix subdir -m "Merged changes from subproject using squash" --squash sub2 &&
-		check_equal ''"$(last_commit_message)"'' "Merged changes from subproject using squash" &&
+test_expect_success 'merge new subproj history into subdir/ with --prefix and --message' '
+		git subtree merge --prefix=subdir --message="Merged changes from subproject" FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Merged changes from subproject" &&
 		undo
 '
 
-test_expect_success 'merge new subproj history into subdir' '
+test_expect_success 'merge new subproj history into subdir/ with --squash and --prefix and --message' '
+		git subtree merge --prefix=subdir --message="Merged changes from subproject using squash" --squash FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Merged changes from subproject using squash" &&
+		undo
+'
+
+test_expect_success 'merge new subproj history into subdir/' '
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git branch pre-split &&
-		check_equal ''"$(last_commit_message)"'' "Merge commit '"'"'"$(git rev-parse sub2)"'"'"' into mainline"
+		git branch pre-split
 '
 
-test_expect_success 'Check that prefix argument is required for split' '
+test_expect_success 'split requires option --prefix' '
 		echo "You must provide the --prefix option." > expected &&
 		test_must_fail git subtree split > actual 2>&1 &&
 		test_debug "echo -n expected: " &&
@@ -190,59 +221,56 @@ test_expect_success 'Check that prefix argument is required for split' '
 		rm -f expected actual
 '
 
-test_expect_success 'Check that the <prefix> exists for a split' '
-		echo "'"'"'non-existent-directory'"'"'" does not exist\; use "'"'"'git subtree add'"'"'" > expected &&
+test_expect_success 'split requires path given by option --prefix must exist' '
+		echo "'\''non-existent-directory'\'' does not exist; use '\''git subtree add'\''" > expected &&
 		test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&
 		test_debug "echo -n expected: " &&
 		test_debug "cat expected" &&
 		test_debug "echo -n actual: " &&
 		test_debug "cat actual" &&
-		test_cmp expected actual
-#		 rm -f expected actual
+		test_cmp expected actual &&
+		rm -f expected actual
 '
 
-test_expect_success 'check if --message works for split+rejoin' '
-		spl1=''"$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
-		git branch spl1 "$spl1" &&
-		check_equal ''"$(last_commit_message)"'' "Split & rejoin" &&
-		undo
-'
+test_expect_success 'split subdir/ with --rejoin' '
+		spl1=$(git subtree split --prefix=subdir --annotate="*") &&
+ 		git branch spl1 "$spl1" &&
+		git subtree split --prefix=subdir --annotate="*" --rejoin &&
+		test_equal "$(last_commit_message)" "Split '\''subdir/'\'' into commit '\''$spl1'\''" &&
+ 		undo
+ '
 
-test_expect_success 'check split with --branch' '
-		spl1=$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin) &&
-		undo &&
-		git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --branch splitbr1 &&
-		check_equal ''"$(git rev-parse splitbr1)"'' "$spl1"
+test_expect_success 'split subdir/ with --rejoin and --message' '
+		git subtree split --prefix=subdir --message="Split & rejoin" --annotate="*" --rejoin &&
+		test_equal "$(last_commit_message)" "Split & rejoin" &&
+		undo
 '
 
-test_expect_success 'check hash of split' '
-        spl1=$(git subtree split --prefix subdir) &&
-        undo &&
-        git subtree split --prefix subdir --branch splitbr1test &&
-        check_equal ''"$(git rev-parse splitbr1test)"'' "$spl1"
-        git checkout splitbr1test &&
-        new_hash=$(git rev-parse HEAD~2) &&
-        git checkout mainline &&
-        check_equal ''"$new_hash"'' "$subdir_hash"
-'
+test_expect_success 'split subdir/ with --branch' '
+		spl1=$(git subtree split --prefix=subdir --message="Split & rejoin" --annotate="*" --rejoin) &&
+ 		undo &&
+		git subtree split --prefix=subdir --annotate="*" --branch splitbr1 &&
+		test_equal "$(git rev-parse splitbr1)" "$spl1"
+ '
 
-test_expect_success 'check split with --branch for an existing branch' '
-		spl1=''"$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
+test_expect_success 'split subdir/ with --branch for an existing branch' '
+		spl1=$(git subtree split --prefix=subdir --annotate="*" --message="Split & rejoin" --rejoin) &&
 		undo &&
 		git branch splitbr2 sub1 &&
-		git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --branch splitbr2 &&
-		check_equal ''"$(git rev-parse splitbr2)"'' "$spl1"
+		git subtree split --prefix=subdir --annotate="*" --branch splitbr2 &&
+		test_equal "$(git rev-parse splitbr2)" "$spl1"
 '
 
-test_expect_success 'check split with --branch for an incompatible branch' '
-		test_must_fail git subtree split --prefix subdir --onto FETCH_HEAD --branch subdir
+test_expect_success 'split subdir/ with --branch for an incompatible branch' '
+		test_must_fail git subtree split --prefix=subdir --branch init
 '
 
-test_expect_success 'check split+rejoin' '
-		spl1=''"$(git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin)"'' &&
+test_expect_success 'check --unannotate' '
+		spl1=$(git subtree split --unannotate="subproj:" --prefix subdir --onto FETCH_HEAD --message "Split & rejoin" --rejoin) &&
 		undo &&
-		git subtree split --annotate='"'*'"' --prefix subdir --onto FETCH_HEAD --rejoin &&
-		check_equal ''"$(last_commit_message)"'' "Split '"'"'subdir/'"'"' into commit '"'"'"$spl1"'"'"'"
+ 		git subtree split --unannotate="subproj:" --prefix subdir --onto FETCH_HEAD --branch splitunann &&
+		test_equal "$(git rev-parse splitunann)" "$spl1" &&
+		test_equal "$(git log splitunann | grep subproj)" ""
 '
 
 test_expect_success 'add main-sub8' '
@@ -268,8 +296,8 @@ test_expect_success 'add sub9' '
 cd ..
 
 test_expect_success 'split for sub8' '
-		split2=''"$(git subtree split --annotate='"'*'"' --prefix subdir/ --rejoin)"''
-		git branch split2 "$split2"
+		spl2=$(git subtree split --prefix=subdir/ --annotate="*" --rejoin) &&
+		git branch spl2 "$spl2"
 '
 
 test_expect_success 'add main-sub10' '
@@ -278,7 +306,7 @@ test_expect_success 'add main-sub10' '
 '
 
 test_expect_success 'split for sub10' '
-		spl3=''"$(git subtree split --annotate='"'*'"' --prefix subdir --rejoin)"'' &&
+		spl3=$(git subtree split --prefix=subdir --annotate="*" --rejoin) &&
 		git branch spl3 "$spl3"
 '
 
@@ -299,13 +327,13 @@ chks="sub1 sub2 sub3 sub9"
 chks_sub=$(echo $chks | multiline | sed 's,^,subdir/,' | fixnl)
 
 test_expect_success 'make sure exactly the right set of files ends up in the subproj' '
-		subfiles=''"$(git ls-files | fixnl)"'' &&
-		check_equal "$subfiles" "$chkms $chks"
+		subfiles=$(git ls-files | fixnl) &&
+		test_equal "$subfiles" "$chkms $chks"
 '
 
-test_expect_success 'make sure the subproj history *only* contains commits that affect the subdir' '
-		allchanges=''"$(git log --name-only --pretty=format:'"''"' | sort | fixnl)"'' &&
-		check_equal "$allchanges" "$chkms $chks"
+test_expect_success 'make sure the subproj *only* contains commits that affect the subdir' '
+		allchanges=$(git log --name-only --pretty=format:"" | sort | fixnl) &&
+		test_equal "$allchanges" "$chkms $chks"
 '
 
 # Back to mainline
@@ -318,25 +346,25 @@ test_expect_success 'pull from subproj' '
 '
 
 test_expect_success 'make sure exactly the right set of files ends up in the mainline' '
-		mainfiles=''"$(git ls-files | fixnl)"'' &&
-		check_equal "$mainfiles" "$chkm $chkms_sub $chks_sub"
+		mainfiles=$(git ls-files | fixnl) &&
+		test_equal "$mainfiles" "$chkm $chkms_sub $chks_sub"
 '
 
 test_expect_success 'make sure each filename changed exactly once in the entire history' '
 		# main-sub?? and /subdir/main-sub?? both change, because those are the
 		# changes that were split into their own history.  And subdir/sub?? never
 		# change, since they were *only* changed in the subtree branch.
-		allchanges=''"$(git log --name-only --pretty=format:'"''"' | sort | fixnl)"'' &&
-		check_equal "$allchanges" ''"$(echo $chkms $chkm $chks $chkms_sub | multiline | sort | fixnl)"''
+		allchanges=$(git log --name-only --pretty=format:"" | sort | fixnl) &&
+		test_equal "$allchanges" "$(echo $chkms $chkm $chks $chkms_sub | multiline | sort | fixnl)"
 '
 
 test_expect_success 'make sure the --rejoin commits never make it into subproj' '
-		check_equal ''"$(git log --pretty=format:'"'%s'"' HEAD^2 | grep -i split)"'' ""
+		test_equal "$(git log --pretty=format:"%s" HEAD^2 | grep -i split)" ""
 '
 
 test_expect_success 'make sure no "git subtree" tagged commits make it into subproj' '
 		# They are meaningless to subproj since one side of the merge refers to the mainline
-		check_equal ''"$(git log --pretty=format:'"'%s%n%b'"' HEAD^2 | grep "git-subtree.*:")"'' ""
+		test_equal "$(git log --pretty=format:"%s%n%b" HEAD^2 | grep "git-subtree.*:")" ""
 '
 
 # prepare second pair of repositories
@@ -374,7 +402,7 @@ cd ../main
 test_expect_success 'add sub as subdir in main' '
 		git fetch ../sub master &&
 		git branch sub2 FETCH_HEAD &&
-		git subtree add --prefix subdir sub2
+		git subtree add --prefix=subdir sub2
 '
 
 cd ../sub
@@ -389,7 +417,7 @@ cd ../main
 test_expect_success 'merge from sub' '
 		git fetch ../sub master &&
 		git branch sub3 FETCH_HEAD &&
-		git subtree merge --prefix subdir sub3
+		git subtree merge --prefix=subdir sub3
 '
 
 test_expect_success 'add main-sub4' '
@@ -398,7 +426,7 @@ test_expect_success 'add main-sub4' '
 '
 
 test_expect_success 'split for main-sub4 without --onto' '
-		git subtree split --prefix subdir --branch mainsub4
+		git subtree split --prefix=subdir --branch mainsub4
 '
 
 # at this point, the new commit parent should be sub3 if it is not,
@@ -407,7 +435,7 @@ test_expect_success 'split for main-sub4 without --onto' '
 # itself)
 
 test_expect_success 'check that the commit parent is sub3' '
-		check_equal ''"$(git log --pretty=format:%P -1 mainsub4)"'' ''"$(git rev-parse sub3)"''
+		test_equal "$(git log --pretty=format:%P -1 mainsub4)" "$(git rev-parse sub3)"
 '
 
 test_expect_success 'add main-sub5' '
@@ -420,49 +448,23 @@ test_expect_success 'split for main-sub5 without --onto' '
 		# also test that we still can split out an entirely new subtree
 		# if the parent of the first commit in the tree is not empty,
 		# then the new subtree has accidently been attached to something
-		git subtree split --prefix subdir2 --branch mainsub5 &&
-		check_equal ''"$(git log --pretty=format:%P -1 mainsub5)"'' ""
+		git subtree split --prefix=subdir2 --branch mainsub5 &&
+		test_equal "$(git log --pretty=format:%P -1 mainsub5)" ""
 '
 
-# make sure no patch changes more than one file.  The original set of commits
-# changed only one file each.  A multi-file change would imply that we pruned
-# commits too aggressively.
-joincommits()
-{
-	commit=
-	all=
-	while read x y; do
-		#echo "{$x}" >&2
-		if [ -z "$x" ]; then
-			continue
-		elif [ "$x" = "commit:" ]; then
-			if [ -n "$commit" ]; then
-				echo "$commit $all"
-				all=
-			fi
-			commit="$y"
-		else
-			all="$all $y"
-		fi
-	done
-	echo "$commit $all"
-}
-
 test_expect_success 'verify one file change per commit' '
 		x= &&
-		list=''"$(git log --pretty=format:'"'commit: %H'"' | joincommits)"'' &&
-#		 test_debug "echo HERE" &&
-#		 test_debug "echo ''"$list"''" &&
-		(git log --pretty=format:'"'commit: %H'"' | joincommits |
-		(		while read commit a b; do
-				test_debug "echo Verifying commit "''"$commit"''
-				test_debug "echo a: "''"$a"''
-				test_debug "echo b: "''"$b"''
-				check_equal "$b" ""
+		git log --pretty=format:"commit: %H" | join_commits |
+		(
+			while read commit a b; do
+				test_debug "echo Verifying commit $commit"
+				test_debug "echo a: $a"
+				test_debug "echo b: $b"
+				test_equal "$b" ""
 				x=1
 			done
-			check_equal "$x" 1
-		))
+			test_equal "$x" 1
+		)
 '
 
 test_done
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 13/13] contrib/subtree: Remove --annotate
From: David A. Greene @ 2013-02-05  4:06 UTC (permalink / raw)
  To: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani
  Cc: David A. Greene
In-Reply-To: <1360037173-23291-1-git-send-email-greened@obbligato.org>

From: "David A. Greene" <greened@obbligato.org>

Remove --annotate.  This obviates the need for an --unannotate
command.  We really want a more generalized commit message rewrite
mechanism.

Signed-off-by: David A. Greene <greened@obbligato.org>
---
 contrib/subtree/git-subtree.sh     |    6 +----
 contrib/subtree/t/t7900-subtree.sh |   50 ++++++++++++++++++------------------
 2 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 0493e47..888a191 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -21,7 +21,6 @@ d             show debug messages
 P,prefix=     the name of the subdir to split out
 m,message=    use the given message as the commit message for the merge commit
  options for 'split'
-annotate=     add a prefix to commit message of new commits
 b,branch=     create a new branch from the split subtree
 ignore-joins  ignore prior --rejoin commits
 onto=         try connecting new tree to an existing one
@@ -43,7 +42,6 @@ command=
 onto=
 rejoin=
 ignore_joins=
-annotate=
 squash=
 message=
 
@@ -79,8 +77,6 @@ while [ $# -gt 0 ]; do
 	case "$opt" in
 		-q) quiet=1 ;;
 		-d) debug=1 ;;
-		--annotate) annotate="$1"; shift ;;
-		--no-annotate) annotate= ;;
 		-b) branch="$1"; shift ;;
 		-P) prefix="${1%/}"; shift ;;
 		-m) message="$1"; shift ;;
@@ -311,7 +307,7 @@ copy_commit()
 			GIT_COMMITTER_NAME \
 			GIT_COMMITTER_EMAIL \
 			GIT_COMMITTER_DATE
-		(echo -n "$annotate"; cat ) |
+		(echo -n ""; cat ) |
 		git commit-tree "$2" $3  # reads the rest of stdin
 	) || die "Can't copy commit $1"
 }
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index 1afd544..59889f1 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -318,8 +318,8 @@ test_expect_success 'split subdir/ with --rejoin' '
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		split_hash=$(git subtree split --prefix=subdir --annotate="*") &&
-		git subtree split --prefix=subdir --annotate="*" --rejoin &&
+		split_hash=$(git subtree split --prefix=subdir) &&
+		git subtree split --prefix=subdir --rejoin &&
 		test_equal "$(last_commit_message)" "Split '\''subdir/'\'' into commit '\''$split_hash'\''"
 	)
  '
@@ -342,7 +342,7 @@ test_expect_success 'split subdir/ with --rejoin and --message' '
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git subtree split --prefix=subdir --message="Split & rejoin" --annotate="*" --rejoin &&
+		git subtree split --prefix=subdir --message="Split & rejoin" --rejoin &&
 		test_equal "$(last_commit_message)" "Split & rejoin"
 	)
 '
@@ -365,8 +365,8 @@ test_expect_success 'split subdir/ with --branch' '
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		split_hash=$(git subtree split --prefix=subdir --annotate="*") &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br &&
+		split_hash=$(git subtree split --prefix=subdir) &&
+		git subtree split --prefix=subdir --branch subproj-br &&
 		test_equal "$(git rev-parse subproj-br)" "$split_hash"
 	)
  '
@@ -390,8 +390,8 @@ test_expect_success 'split subdir/ with --branch for an existing branch' '
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		split_hash=$(git subtree split --prefix=subdir --annotate="*") &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br &&
+		split_hash=$(git subtree split --prefix=subdir) &&
+		git subtree split --prefix=subdir --branch subproj-br &&
 		test_equal "$(git rev-parse subproj-br)" "$split_hash"
 	)
 '
@@ -441,7 +441,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count/subproj" sub3 &&
 	test_create_commit "$test_count" subdir/main-sub3 &&
@@ -452,12 +452,12 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub
 	test_create_commit "$test_count/subproj" sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count" subdir/main-sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	(
 		cd "$test_count/subproj" &&
@@ -491,7 +491,7 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count/subproj" sub3 &&
 	test_create_commit "$test_count" subdir/main-sub3 &&
@@ -502,12 +502,12 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t
 	test_create_commit "$test_count/subproj" sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count" subdir/main-sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	(
 		cd "$test_count/subproj" &&
@@ -541,7 +541,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count/subproj" sub3 &&
 	test_create_commit "$test_count" subdir/main-sub3 &&
@@ -552,12 +552,12 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai
 	test_create_commit "$test_count/subproj" sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count" subdir/main-sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	(
 		cd "$test_count/subproj" &&
@@ -595,7 +595,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count/subproj" sub3 &&
 	test_create_commit "$test_count" subdir/main-sub3 &&
@@ -606,12 +606,12 @@ test_expect_success 'make sure each filename changed exactly once in the entire
 	test_create_commit "$test_count/subproj" sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count" subdir/main-sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	(
 		cd "$test_count/subproj" &&
@@ -653,7 +653,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count/subproj" sub3 &&
 	test_create_commit "$test_count" subdir/main-sub3 &&
@@ -664,12 +664,12 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'
 	test_create_commit "$test_count/subproj" sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count" subdir/main-sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	(
 		cd "$test_count/subproj" &&
@@ -701,7 +701,7 @@ test_expect_success 'make sure no "git subtree" tagged commits make it into subp
 		cd "$test_count" &&
 		git fetch ./subproj master &&
 		git subtree merge --prefix=subdir FETCH_HEAD &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count/subproj" sub3 &&
 	test_create_commit "$test_count" subdir/main-sub3 &&
@@ -712,12 +712,12 @@ test_expect_success 'make sure no "git subtree" tagged commits make it into subp
 	test_create_commit "$test_count/subproj" sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	test_create_commit "$test_count" subdir/main-sub4 &&
 	(
 		cd "$test_count" &&
-		git subtree split --prefix=subdir --annotate="*" --branch subproj-br --rejoin
+		git subtree split --prefix=subdir --branch subproj-br --rejoin
 	) &&
 	(
 		cd "$test_count/subproj" &&
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 12/13] contrib/subtree: Handle '--prefix' argument with a slash appended
From: David A. Greene @ 2013-02-05  4:06 UTC (permalink / raw)
  To: James Nylen, git, Techlive Zheng, Wayne Walter,
	Avery Pennarun ", Jakub Suder, John Yani
  Cc: David A. Greene
In-Reply-To: <1360037173-23291-1-git-send-email-greened@obbligato.org>

From: Techlive Zheng <techlivezheng@gmail.com>

'git subtree merge' will fail if the argument of '--prefix' has a slash
appended.

Signed-off-by: Techlive Zheng <techlivezheng@gmail.com>
Signed-off-by: David A. Greene <greened@obbligato.org>
---
 contrib/subtree/git-subtree.sh     |    2 +-
 contrib/subtree/t/t7900-subtree.sh |   19 +++++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index c72af95..0493e47 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -82,7 +82,7 @@ while [ $# -gt 0 ]; do
 		--annotate) annotate="$1"; shift ;;
 		--no-annotate) annotate= ;;
 		-b) branch="$1"; shift ;;
-		-P) prefix="$1"; shift ;;
+		-P) prefix="${1%/}"; shift ;;
 		-m) message="$1"; shift ;;
 		--no-prefix) prefix= ;;
 		--onto) onto="$1"; shift ;;
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index 769b116..1afd544 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -239,6 +239,25 @@ test_expect_success 'merge new subproj history into subdir/ with --squash and --
 	)
 '
 
+test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '
+	test_create_repo "$test_count" &&
+	test_create_repo "$test_count/subproj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/subproj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree add --prefix=subdir/ FETCH_HEAD
+	) &&
+	test_create_commit "$test_count/subproj" sub2 &&
+	(
+		cd "$test_count" &&
+		git fetch ./subproj master &&
+		git subtree merge --prefix=subdir/ FETCH_HEAD &&
+		test_equal "$(last_commit_message)" "Merge commit '\''$(git rev-parse FETCH_HEAD)'\''"
+	)
+'
+
 #
 # Tests for 'git subtree split'
 #
-- 
1.7.10.4

^ permalink raw reply related


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