Git development
 help / color / mirror / Atom feed
* Re: [PATCH] binary patch.
From: Nicolas Pitre @ 2006-05-05 18:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vejz8z80p.fsf@assigned-by-dhcp.cox.net>

On Fri, 5 May 2006, Junio C Hamano wrote:

> Nicolas Pitre <nico@cam.org> writes:
> 
> >> +	delta = NULL;
> >> +	deflated = deflate_it(two->ptr, two->size, &deflate_size);
> >> +	if (one->size && two->size) {
> >> +		delta = diff_delta(one->ptr, one->size,
> >> +				   two->ptr, two->size,
> >> +				   &delta_size, deflate_size);
> >
> > Here you probably want to use deflate_size-1 (deflate_size can't be 0).
> 
> I am not sure if -1 is worth here.
> 
> The delta is going to be deflated and hopefully gets a bit
> smaller, so if we really care that level of detail, it might be
> worth to do (deflate_size*3/2) or something like that here, use
> delta with or without deflate whichever is smaller, and mark the
> uncompressed delta with a different tag ("uncompressed delta"?).
> And for symmetry, to deal with uncompressible data, we may want
> to have "uncompressed literal" as well.

Nah...  Please just forget that.  ;-)


Nicolas

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Linus Torvalds @ 2006-05-05 18:31 UTC (permalink / raw)
  To: Petr Baudis; +Cc: linux, git
In-Reply-To: <20060505181540.GB27689@pasky.or.cz>



On Fri, 5 May 2006, Petr Baudis wrote:
> 
> The automatic vs. explicit movement tracking is a lot more
> controversial. Explicit movement tracking is pretty easy to provide for
> file-level movements, it's just that the user says "I _did_ move file
> A to file B" (I never got the Linus' argument that the user has no idea
> - he just _performed_ the move, also explicitly, by calling *mv).

THE USER DID NO SUCH THING.

Moving data around happens with a whole lot more than "mv".

It happens with patches (somebody _else_ may have done an "mv", without 
using git at all), and it happens with editors (moving data around until 
most of it exists in another file).

So doing "*mv" is just a special case.

And supporting special cases is _wrong_. If you start depending on data 
that isn't actually dependable, that's WRONG.

There's another reason why encoding movement information in the commit is 
totally broken, namely the fact that a lot of the actions DO NOT WALK THE 
COMMIT CHAIN!

Try doing

	git diff v1.3.0..

and think about what that actually _means_. Think about the fact that it 
doesn't actually walk the commit chain at all: it diffs the trees between 
v1.3.0 and the current one. What if the rename happened in a commit in the 
middle?

The "track contents, not intentions" approach avoids both these things. 
The end result is _reliable_, not a "random guess".

Adding file movement note to commits is simply WRONG.

Why does this come up every three months or so? I was right the first 
time. You'd think that as time passes, people would just notice more and 
more how right I was and am, instead of forgetting and bringing this 
idiotic idea up over and over and over again.

		Linus

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Jakub Narebski @ 2006-05-05 18:27 UTC (permalink / raw)
  To: git
In-Reply-To: <20060505181540.GB27689@pasky.or.cz>

Petr Baudis wrote:

> The automatic vs. explicit movement tracking is a lot more
> controversial. Explicit movement tracking is pretty easy to provide for
> file-level movements, it's just that the user says "I _did_ move file
> A to file B" (I never got the Linus' argument that the user has no idea
> - he just _performed_ the move, also explicitly, by calling *mv).
> 
> However, I guess the explicit movement tracking completely fails if you
> go sub-file (without being extremely bothersome for the user) - you
> would have to have control over the editor and the clipboard and even
> then I'm not sure if you could reach any sensible results.

If I remember correctly there are some problems if the explicit file-level
contents movement tracking (aka. file rename tracking) is done via
equivalent of file-id, inodes, or persistent names. Although it works for
many (most?) cases.

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Petr Baudis @ 2006-05-05 18:20 UTC (permalink / raw)
  To: linux; +Cc: git
In-Reply-To: <20060505181540.GB27689@pasky.or.cz>

Dear diary, on Fri, May 05, 2006 at 08:15:41PM CEST, I got a letter
where Petr Baudis <pasky@suse.cz> said that...
> There are really two distinctions here which should be kept separate:
> automatic vs. explicit movement tracking and file-level vs.
> subfile-level movement tracking.

I should have revised this paragraph before sending the mail out, I
ended up sorting out my thoughts on the subject as I wrote the mail. The
two aspects end up so tied that it makes sense to mingle them. Examining
them separately here still hopefully shed some light on possible
reasoning behind the Git design decisions.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Right now I am having amnesia and deja-vu at the same time.  I think
I have forgotten this before.

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Petr Baudis @ 2006-05-05 18:15 UTC (permalink / raw)
  To: linux; +Cc: git
In-Reply-To: <20060505005659.9092.qmail@science.horizon.com>

Dear diary, on Fri, May 05, 2006 at 02:56:59AM CEST, I got a letter
where linux@horizon.com said that...
> But, as Linus has pointed out, this is a very partial solution which
> introduces a lot of difficulties elsewhere.  File renaming is a subset of
> the general class of code reorganizations.  Source files will be split,
> merged, and have functions moved back and forth.  You want the patch to
> find the code it applies to even if that code was moved.
> 
> And that can be done by taking a more global view of the patch.
> Identical file names is only a heuristic.  If the hunk on branch A
> can't find a place to apply on the same file in branch B, then
> you have to look a little harder, either at changes from branch B
> that introduce matching code elsewhere, or perhaps looking
> through history for a change that removed the match from the
> obvious place to see if it added a match elsewhere.

There are really two distinctions here which should be kept separate:
automatic vs. explicit movement tracking and file-level vs.
subfile-level movement tracking.

The automatic vs. explicit movement tracking is a lot more
controversial. Explicit movement tracking is pretty easy to provide for
file-level movements, it's just that the user says "I _did_ move file
A to file B" (I never got the Linus' argument that the user has no idea
- he just _performed_ the move, also explicitly, by calling *mv).

However, I guess the explicit movement tracking completely fails if you
go sub-file (without being extremely bothersome for the user) - you
would have to have control over the editor and the clipboard and even
then I'm not sure if you could reach any sensible results.

I still dislike automated movement tracking for whole files, but I'm
conciliated with it. Because it is probably the only really sensible way
to implement subfile-level tracking.  It would not be hard to implement
using pickaxe (actually, I believe it was near the top of Junio's TODO
few weeks ago) and a similarity detector comparing new and old version
(if it's dissimilar enough, check if that or a similar hunk was not
added somewhere else in the same commit; well, at least the idea
sounds simple).

One obvious problem are ambiguities - several similar files are renamed
to other similar files and now how do you decide which version to
choose? Merge the change to all the new files? Only to some? Panic?
I wonder how does the current recursive strategy deal with that.
Of course, this case sounds quite artificial and rare for whole files,
but I suspect that it will be much more common once you do not deal with
files but just hunks, moving bits of code around.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Right now I am having amnesia and deja-vu at the same time.  I think
I have forgotten this before.

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Linus Torvalds @ 2006-05-05 17:48 UTC (permalink / raw)
  To: Petr Baudis; +Cc: linux, Git Mailing List
In-Reply-To: <20060505163629.GZ27689@pasky.or.cz>



On Fri, 5 May 2006, Petr Baudis wrote:
> 
> It's a philosophical question here, but I'd say that Git is much closer
> to Monotone than to any other version control system

Some historical background..

Before I dropped BK, I ended up being involved in trying to get Larry and 
Tridge to come to some agreement about how to solve the issues Tridge had 
with BK not being open-source. That actually went on for maybe two months 
or so, and I kept on hoping that we'd find some acceptably middle ground. 

I thought we could find somethign that would actually work for everybody: 
to hopefully both make BK technically better, _and_ to make the end result 
more palatable to the "free software or bust" contingency.

One of the suggestions that I tried to push as an acceptable middle ground 
was to make a "generic" BK repository export format, so that people who 
didn't want to use BK could still get all the information, and not in a 
broken format like CVS (yes, CVS makes sense as an interchange format, 
since _everybody_ speaks CVS, but it's a horrible, horrible, horrible 
format from any technical standpoint).

My example export format was really a strange mixture of patches with 
parenthood information, where the history information was described with 
hashes (MD5 rather than SHA1, but that was just an implementation thing, 
and mostly because BK used MD5 sums). Not something really useful as a 
real SCM, but it wasn't designed for that - it was just meant to be a 
useful and unambiguous interoperability format.

Now, that didn't work out, and I was a little bummed. I thought it would 
have made both sides happy, because it would actually have been a better 
format than CVS (and yes, I'm somewhat biased: in my opinion, having a 
million monkeys throwing crap at the walls and encoding the information in 
the patterns on monkey shit is a better format than CVS), so it would 
actually have improved BK, while also making it possible to interoperate 
if you didn't want to use BK itself.

But Tridge didn't believe that it would actually have exported all the 
information in a BK tree, even if both I and Larry told him it would. I'm 
not a hundred percent sure that Larry would have gone for the export 
format either, but hey, one sign of a good compromise is that neither side 
really gets what they really want. Whatever. It didn't work.

So it didn't actually resolve the deadlock, but when it became clear that 
I couldn't work with BK any more, I thought I might use something like 
that "patch + parenthood" representation as a way to maintain my tree 
while looking at other alternatives.

So in many ways, when I started looking around for distributed SCM's, I 
came into the game with the background of keeping the history around as 
chains of hashes describing it, and then just having patches to describe 
the differences between versions.

So that was really my "fallback" position: if nothing out there worked, 
I'd rather go back to lists of patches than use CVS. 

Now, if you keep track of just patches, one of the issues is that you 
can't afford to re-create the tree every time by walking patches forward 
from the beginning, so I also was planning to have an "cache" that 
maintained the current state of the tree as a separate state from the 
working tree, so that I would always have the "working tree" and the 
"result of patches up to this moment" as two separate things (so that I 
could do the "bk diff" that I was used to doing to see the difference 
between my last state and the current state of the working tree).

In other words, I was already working on the git "index" file. And I was 
planning to just have a patch-based system behind it, with a hashed 
history. Kind of "quilt with history and an index to speed things up".

The index itself would be backed-up with whole files (all hidden in the 
".dircache" directory), and the patch series would thus normally never 
actually be _used_. So the inefficiency of working with patches would 
never be much of an issue. A "commit" would create a new patch from the 
current working directory and the previous shadow tree, and update the 
shadow tree and add a new entry to the history list.

And then I found Monotone.

Now, monotone was slow. Monotone was so _horrendously_ slow that I had to 
do special hacks just to import _one_ version of Linux into it in less 
than two hours. It was something stupid like an O(N**3) algorithm in the 
number of filenames (and the kernel had 17,291 files at that time: 
v2.6.12-rc2), and it was just totally unusable for me.

I also thought (and still think) that the whole signing thing was a waste 
of time and misdesigned, and I obviously am not a huge fan of databases. 
So in many ways I disliked the monotone implementation decisions (and some 
of its design decisions). But at the same time, I immediately liked the 
SHA1 object naming concept of Monotone.

It also already matched how I had conceptually planned on doing on the 
history anyway, and had some ideas for, but it took that whole "history 
hashing" all the way.

And thus git was born. 

So git really has three parents. In a very real sense, BK (or, perhaps 
more appropriately - the way I personally used BK, which is not 
necessarily how others have used it) was the biggest thing from the 
standpoint of what I wanted my _workflow_ to be like. It was simply how I 
had done things for the last few years, so a lot of my mental model for 
how things are supposed to _work_ came from BK. 

I still don't think people give Larry enough credit for actually pushing 
this whole distributed SCM thing as a _usable_ model. Very few of the 
open-source distributed SCM's are actually usable even today, and as far 
as I've been able to gather, the commercial ones aren't really any closer 
either. Larry didn't have the kind of examples of what _can_ work that I 
had.

The other parent was the stupid "series of patches" model, which was what 
really resulted in the "index" thing. I realize that people don't always 
much like the index, but it's really a pretty central part of git history, 
and one of the distinguising marks of git. It may be trivial, and to some 
degree it's been overshadowed by all the tree operations we do (the 
combination of revision walking and tree diffing), but it was very central 
to how git came to be.

The index also ended up being central to how we did merges - even if some 
day we may end up doing more of that on a pure tree level (ie the current 
git-merge-tree model), I think the way we ended up doing merges owes a lot 
to the index as a staging area.

(Historically, the "index" was called the "cache". Exactly because it came 
from the notion of "caching" the top commit state in a patch series, and 
then working with patches either backwards or forwards from that top 
cached state. Similarly, we didn't have a ".git" directory: it was 
called ".dircache", exactly because it was all about caching the state 
of the previous commit directory layout).

And finally, Monotone for the "everything is an object named by its SHA1" 
model, which to some degree is perhaps the central - or at least the most 
obvious - part of git. It largely was designed really just to be the 
"backing store" for the "cache", and to not be _that_ important. That also 
explains why I didn't worry too much about disk usage etc initially: the 
object store wasn't even the most important part, and I envisioned just 
moving old objects that weren't needed into some "backup storage" kind of 
thing.

			Linus

^ permalink raw reply

* Re: [PATCH] binary patch.
From: Junio C Hamano @ 2006-05-05 17:38 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605051128100.28543@localhost.localdomain>

Nicolas Pitre <nico@cam.org> writes:

>> +	delta = NULL;
>> +	deflated = deflate_it(two->ptr, two->size, &deflate_size);
>> +	if (one->size && two->size) {
>> +		delta = diff_delta(one->ptr, one->size,
>> +				   two->ptr, two->size,
>> +				   &delta_size, deflate_size);
>
> Here you probably want to use deflate_size-1 (deflate_size can't be 0).

I am not sure if -1 is worth here.

The delta is going to be deflated and hopefully gets a bit
smaller, so if we really care that level of detail, it might be
worth to do (deflate_size*3/2) or something like that here, use
delta with or without deflate whichever is smaller, and mark the
uncompressed delta with a different tag ("uncompressed delta"?).
And for symmetry, to deal with uncompressible data, we may want
to have "uncompressed literal" as well.

>> +		orig_size = delta_size;
>> +		if (delta)
>> +			delta = deflate_it(delta, delta_size, &delta_size);
>
> Here you're leaking the original delta buffer memory.

Indeed.  Thanks.

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Jakub Narebski @ 2006-05-05 16:47 UTC (permalink / raw)
  To: git
In-Reply-To: <7vejz8241m.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:

> Petr Baudis <pasky@suse.cz> writes:
> 
>> But the non-obviously important part here to note is that the branch B
>> merely "corrects a typo on a comment somewhere" - the latest versions in
>> branch A and branch B are always compared for renames, therefore if
>> branch A renamed the file and branch B sums up to some larger-scale
>> changes in the file, it still won't be merged properly.
> 
> I probably am guilty of starting this misinformation, but the
> code does not compare the latest in A and B for rename
> detection; it compares (O, A) and (O, B).
> 
> But the end result is the same - what you say is correct.  If a
> path (say O to A) that renamed has too big a change, then no
> matter how small the changes are on the other path (O to B),
> rename detection can be fooled.  We could perhaps alleviate it
> by following the whole commit chain.

Or perhaps by helper information about renames, entered either by git-mv
(and git-cp) or rename detection at commit, e.g. in the following form

        note at <commit-sha1> was-in <pathname>
        note at <commit-sha1> was-in <pathname>

(with the obvious limit of this "note header" solution is that it wouldn't
work for filenames and directory name containing "\n"). I'm not sure if
<pathname> should be just basename, of full pathname.

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Petr Baudis @ 2006-05-05 16:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vejz8241m.fsf@assigned-by-dhcp.cox.net>

Dear diary, on Fri, May 05, 2006 at 11:51:01AM CEST, I got a letter
where Junio C Hamano <junkio@cox.net> said that...
> Petr Baudis <pasky@suse.cz> writes:
> 
> > But the non-obviously important part here to note is that the branch B
> > merely "corrects a typo on a comment somewhere" - the latest versions in
> > branch A and branch B are always compared for renames, therefore if
> > branch A renamed the file and branch B sums up to some larger-scale
> > changes in the file, it still won't be merged properly.
> 
> I probably am guilty of starting this misinformation, but the
> code does not compare the latest in A and B for rename
> detection; it compares (O, A) and (O, B).

Where O = LCA(A,B) (modulo recursiveness)? Yes, that is what I meant to
say but I phrased it wrong, sorry.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Right now I am having amnesia and deja-vu at the same time.  I think
I have forgotten this before.

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Petr Baudis @ 2006-05-05 16:36 UTC (permalink / raw)
  To: linux; +Cc: git
In-Reply-To: <20060505005659.9092.qmail@science.horizon.com>

Dear diary, on Fri, May 05, 2006 at 02:56:59AM CEST, I got a letter
where linux@horizon.com said that...
> Actually, AFAICT from looking at the mailing list history, it's not dirty
> politics: the tie-breaker was the support and enthusiasm of the mercurial
> developers.  It passed with only minor comment on the git mailing list,
> but it was a Big Thing to the hg folks.
> 
> There are ups and downs.  OpenSolaris is definitely the big fish in
> the mercurial pond (that wasn't *meant* to sound like a recipe for
> heavy metal toxicity), and will get lots of attention, but git has more
> real-world experience.  The big fish in the git pond is Linus and Linux.
> 
> In any case, mercurial and git are really very similar, far closer
> to each other than any third system, so it's not like the decision is
> a descent into heresy.  Hopefully some useful cross-pollination
> can occur, and converting history from one to the other would be
> simple if anyone ever wanted to.

It's a philosophical question here, but I'd say that Git is much closer
to Monotone than to any other version control system - I think it can be
described as Monotone model with more elegant implementation (for some,
at least ;), no certificates and restriction of one head per branch.
And another important difference is that Monotone has persistent file
identifiers, but I think that's about the only thing that would make
Monotone more "file orientated".

I'm not much of a Mercurial pro but it appears to me that the
architectural differences there are larger, especially wrt. the revlogs
and wholly quite a more file-oriented model.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Right now I am having amnesia and deja-vu at the same time.  I think
I have forgotten this before.

^ permalink raw reply

* Re: Unresolved issues #2 (shallow clone again)
From: Linus Torvalds @ 2006-05-05 15:59 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <e3fqb9$hed$1@sea.gmane.org>



On Fri, 5 May 2006, Jakub Narebski wrote:

> Linus Torvalds wrote:
> 
> > So what you'd get is a _really_ cut down history that doesn't contain any
> > commit history at all (just distinct "points in commit history time"), but
> > that _does_ contain all the objects that the commits point to.
> 
> So we would get 'skin-deep clone' rather than 'shallow' one?

Well, it's really shallow, but perhaps more importantly, I think it should 
be really easy, and have totally unambiguous semantics. Never any question 
of how far back to go, and I think we already really do have all the 
support logic for doing it.

Now, we don't actually expose the internal "no_walk" flag with a 
"--no-walk" command line argument parsing, but that's a one-liner.

There's another approach that might be a bit friendlier, which is again to 
walk only the objects of the WANT/HAVE things, but then _do_ walk the 
history for just commit objects. Something close to what I think the http 
fetch thing does if you pass it "-c -t". That too shouldn't require too 
much extra complexity, and it would mean that "git log" at least works.

Of course, that would require another slight difference to "rev-list.c", 
where we'd only recurse into trees of selected commit objects (ie we'd 
have to mark the HAVE/WANT commits specially, but it's not exactly 
complex either).

Of course, the complexity of _both_ of these approaches is really in the 
fsck stage, and all the crud you need to then do other things with these 
pared-down repos. For example, do you allow cloning? And do you just 
automatically notice that you're cloning a shallow repo, and only do a 
shallow clone. Etc etc..

		Linus

^ permalink raw reply

* Re: [PATCH] binary patch.
From: Nicolas Pitre @ 2006-05-05 15:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vy7xgzsiu.fsf@assigned-by-dhcp.cox.net>

On Fri, 5 May 2006, Junio C Hamano wrote:

> > Yeah, things still to be done are deflating both delta and
> > optionally perhaps use just deflate without delta for "new file"
> > codepath.

> +	/* We could do deflated delta, or we could do just deflated two,
> +	 * whichever is smaller.
> +	 */
> +	delta = NULL;
> +	deflated = deflate_it(two->ptr, two->size, &deflate_size);
> +	if (one->size && two->size) {
> +		delta = diff_delta(one->ptr, one->size,
> +				   two->ptr, two->size,
> +				   &delta_size, deflate_size);

Here you probably want to use deflate_size-1 (deflate_size can't be 0).

> +		orig_size = delta_size;
> +		if (delta)
> +			delta = deflate_it(delta, delta_size, &delta_size);

Here you're leaking the original delta buffer memory.


Nicolas

^ permalink raw reply

* Re: Unresolved issues #2 (shallow clone again)
From: Carl Worth @ 2006-05-05 15:31 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0605050806370.3622@g5.osdl.org>

[-- Attachment #1: Type: text/plain, Size: 939 bytes --]

On Fri, 5 May 2006 08:10:50 -0700 (PDT), Linus Torvalds wrote:
> 
> Namely just have a mode to "git-send-pack" that uses the "--no-walk" flag 
> to generate the object list to send.
> 
> What that does is to never walk the object history: so it will just use 
> the "I HAVE THESE" and "I WANT THESE" commit references to directly 
> generate the list of commits, and then walks the trees to generate the 
> list of trees/blobs that differ between the particular end-points.

Oh, I think that's a great idea. I had proposed cutting the WANT list
down to a single commit, but I wasn't clever enough to think to also
cut down the HAVE walking to solve the problems that would have been
introduced by shallow clones.

And I think the resulting behavior is quite reasonable. I think one
can argue a sort of zero-one-infinity rule here. With history, either
you don't care about any of it, or else you really should care about
all of it.

-Carl

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: Unresolved issues #2 (shallow clone again)
From: Jakub Narebski @ 2006-05-05 15:18 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.64.0605050806370.3622@g5.osdl.org>

Linus Torvalds wrote:

> So what you'd get is a _really_ cut down history that doesn't contain any
> commit history at all (just distinct "points in commit history time"), but
> that _does_ contain all the objects that the commits point to.

So we would get 'skin-deep clone' rather than 'shallow' one?

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply

* Re: Unresolved issues #2 (shallow clone again)
From: Linus Torvalds @ 2006-05-05 15:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Carl Worth, git
In-Reply-To: <7v1wv92u7o.fsf@assigned-by-dhcp.cox.net>



On Thu, 4 May 2006, Junio C Hamano wrote:
> 
> Jokes aside, I think listing the updated conversation elements
> like you did above is a good step forward.
> 
> The vocabulary we would want from the requestor side is probably
> (at least):
> 
> 	I WANT to have these
>         I HAVE these
>         I'm MISSING these
>         Don't bother with these this time around (--since, ^v2.6.16, ...)

Actually, I think we can do something simpler that _most_ people might be 
happy with.

Namely just have a mode to "git-send-pack" that uses the "--no-walk" flag 
to generate the object list to send.

What that does is to never walk the object history: so it will just use 
the "I HAVE THESE" and "I WANT THESE" commit references to directly 
generate the list of commits, and then walks the trees to generate the 
list of trees/blobs that differ between the particular end-points.

We already have the "no_walk" flag internally, we just don't expose it.

So what you'd get is a _really_ cut down history that doesn't contain any 
commit history at all (just distinct "points in commit history time"), but 
that _does_ contain all the objects that the commits point to.

		Linus

^ permalink raw reply

* [PATCH] Fix for config file section parsing.
From: sean @ 2006-05-05 13:49 UTC (permalink / raw)
  To: git

Currently, if the target key has a section that matches
the initial substring of another section we mistakenly
believe we've found the correct section.  To avoid this
problem, ensure that the section lengths are identical
before comparison.

Signed-off-by: Sean Estabrooks <seanlkml@sympatico.ca>

---

Here's an example of the problem:

$ git repo-config a.b.c d
$ cat .git/config
[a.b]
        c = d
$ git repo-config a.x y
$ cat .git/config
[a.b]
        c = d
        x = y


 config.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

f956fd1a6b1d3c82d9bc735427b58ec41d9e5dd1
diff --git a/config.c b/config.c
index 4e1f0c2..a3e14d7 100644
--- a/config.c
+++ b/config.c
@@ -335,8 +335,9 @@ static int store_aux(const char* key, co
 			store.offset[store.seen] = ftell(config_file);
 			store.state = KEY_SEEN;
 			store.seen++;
-		} else if(!strncmp(key, store.key, store.baselen))
-			store.state = SECTION_SEEN;
+		} else if (strrchr(key, '.') - key == store.baselen &&
+			      !strncmp(key, store.key, store.baselen))
+					store.state = SECTION_SEEN;
 	}
 	return 0;
 }
-- 
1.3.2.g2fb9

^ permalink raw reply related

* Re: [PATCH/RFC (git-core)] squelch pack-object eye-candy on non-tty
From: Johannes Schindelin @ 2006-05-05 11:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmzdwzsar.fsf@assigned-by-dhcp.cox.net>

Hi,

On Fri, 5 May 2006, Junio C Hamano wrote:

> This defaults not to do the progress report when not on a tty.

Melikes,
Dscho

^ permalink raw reply

* [PATCH/RFC (git-core)] squelch pack-object eye-candy on non-tty
From: Junio C Hamano @ 2006-05-05 10:20 UTC (permalink / raw)
  To: git

One of my post-update scripts runs a git-fetch into a separate
repository and sends the results back to me (2>&1); I end up
getting this in the mail:

    Generating pack...
    Done counting 180 objects.
    Result has 131 objects.
    Deltifying 131 objects.
       0% (0/131) done^M   1% (2/131) done^M...

This defaults not to do the progress report when not on a tty.

You could give --progress to force the progress report, but
let's not bother even documenting it nor mentioning it in the
usage string.

---
diff --git a/pack-objects.c b/pack-objects.c
index 6604338..53caed4 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -1239,6 +1239,7 @@ int main(int argc, char **argv)
 
 	setup_git_directory();
 
+	progress = isatty(2);
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 
@@ -1269,6 +1270,10 @@ int main(int argc, char **argv)
 					usage(pack_usage);
 				continue;
 			}
+			if (!strcmp("--progress", arg)) {
+				progress = 1;
+				continue;
+			}
 			if (!strcmp("-q", arg)) {
 				progress = 0;
 				continue;

^ permalink raw reply related

* Re: [PATCH] binary patch.
From: Junio C Hamano @ 2006-05-05 10:15 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: git
In-Reply-To: <7vwtd10xyd.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> Nicolas Pitre <nico@cam.org> writes:
>
>> This is nice.
>>
>> However I'd deflate the delta data before encoding it with base85.
>
> Yeah, things still to be done are deflating both delta and
> optionally perhaps use just deflate without delta for "new file"
> codepath.
>
> And testsuite.

-- >8 --
[PATCH] binary diff: further updates.

This updates the user interface and generated diff data format.

 * "diff --binary" is used to signal that we want an e-mailable
   binary patch.  It implies --full-index and -p.

 * "apply --allow-binary-replacement" acquired a short synonym
   "apply --binary".

 * After the "GIT binary patch\n" header line there is a token
   to record which binary patch mechanism was used, so that we
   can extend it later.  Currently there are two mechanisms
   defined: "literal" and "delta".  The former records the
   deflated postimage and the latter records the deflated delta
   from the preimage to postimage.

   For purely implementation convenience, I added the deflated
   length after these "literal/delta" tokens (otherwise the
   decoding side needs to guess and reallocate the buffer while
   inflating).  Improvement patches are very welcomed.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 * Have done only very minimum testing, and unlike somebody else ;-)
   my code is not always perfect, so this will still stay out of
   "next" for a while.

 apply.c |  130 +++++++++++++++++++++++++++++++++++++++++++++----------------
 cache.h |    1 
 diff.c  |  135 +++++++++++++++++++++++++++++++++------------------------------
 diff.h  |    1 
 4 files changed, 169 insertions(+), 98 deletions(-)

diff --git a/apply.c b/apply.c
index e37c4eb..1b93aab 100644
--- a/apply.c
+++ b/apply.c
@@ -114,6 +114,9 @@ struct patch {
 	char *new_name, *old_name, *def_name;
 	unsigned int old_mode, new_mode;
 	int is_rename, is_copy, is_new, is_delete, is_binary;
+#define BINARY_DELTA_DEFLATED 1
+#define BINARY_LITERAL_DEFLATED 2
+	unsigned long deflate_origlen;
 	int lines_added, lines_deleted;
 	int score;
 	struct fragment *fragments;
@@ -969,9 +972,11 @@ static inline int metadata_changes(struc
 
 static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
 {
-	/* We have read "GIT binary patch\n"; what follows is a
-	 * sequence of 'length-byte' followed by base-85 encoded
-	 * delta data.
+	/* We have read "GIT binary patch\n"; what follows is a line
+	 * that says the patch method (currently, either "deflated
+	 * literal" or "deflated delta") and the length of data before
+	 * deflating; a sequence of 'length-byte' followed by base-85
+	 * encoded data follows.
 	 *
 	 * Each 5-byte sequence of base-85 encodes up to 4 bytes,
 	 * and we would limit the patch line to 66 characters,
@@ -982,11 +987,27 @@ static int parse_binary(char *buffer, un
 	 */
 	int llen, used;
 	struct fragment *fragment;
-	char *delta = NULL;
+	char *data = NULL;
 
-	patch->is_binary = 1;
 	patch->fragments = fragment = xcalloc(1, sizeof(*fragment));
-	used = 0;
+
+	/* Grab the type of patch */
+	llen = linelen(buffer, size);
+	used = llen;
+	linenr++;
+
+	if (!strncmp(buffer, "delta ", 6)) {
+		patch->is_binary = BINARY_DELTA_DEFLATED;
+		patch->deflate_origlen = strtoul(buffer + 6, NULL, 10);
+	}
+	else if (!strncmp(buffer, "literal ", 8)) {
+		patch->is_binary = BINARY_LITERAL_DEFLATED;
+		patch->deflate_origlen = strtoul(buffer + 8, NULL, 10);
+	}
+	else
+		return error("unrecognized binary patch at line %d: %.*s",
+			     linenr-1, llen-1, buffer);
+	buffer += llen;
 	while (1) {
 		int byte_length, max_byte_length, newsize;
 		llen = linelen(buffer, size);
@@ -1015,8 +1036,8 @@ static int parse_binary(char *buffer, un
 		    byte_length <= max_byte_length - 4)
 			goto corrupt;
 		newsize = fragment->size + byte_length;
-		delta = xrealloc(delta, newsize);
-		if (decode_85(delta + fragment->size,
+		data = xrealloc(data, newsize);
+		if (decode_85(data + fragment->size,
 			      buffer + 1,
 			      byte_length))
 			goto corrupt;
@@ -1024,7 +1045,7 @@ static int parse_binary(char *buffer, un
 		buffer += llen;
 		size -= llen;
 	}
-	fragment->patch = delta;
+	fragment->patch = data;
 	return used;
  corrupt:
 	return error("corrupt binary patch at line %d: %.*s",
@@ -1425,6 +1446,61 @@ #endif
 	return offset;
 }
 
+static char *inflate_it(const void *data, unsigned long size,
+			unsigned long inflated_size)
+{
+	z_stream stream;
+	void *out;
+	int st;
+
+	memset(&stream, 0, sizeof(stream));
+
+	stream.next_in = (unsigned char *)data;
+	stream.avail_in = size;
+	stream.next_out = out = xmalloc(inflated_size);
+	stream.avail_out = inflated_size;
+	inflateInit(&stream);
+	st = inflate(&stream, Z_FINISH);
+	if ((st != Z_STREAM_END) || stream.total_out != inflated_size) {
+		free(out);
+		return NULL;
+	}
+	return out;
+}
+
+static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
+{
+	unsigned long dst_size;
+	struct fragment *fragment = patch->fragments;
+	void *data;
+	void *result;
+
+	data = inflate_it(fragment->patch, fragment->size,
+			  patch->deflate_origlen);
+	if (!data)
+		return error("corrupt patch data");
+	switch (patch->is_binary) {
+	case BINARY_DELTA_DEFLATED:
+		result = patch_delta(desc->buffer, desc->size,
+				     data,
+				     patch->deflate_origlen,
+				     &dst_size);
+		free(desc->buffer);
+		desc->buffer = result;
+		free(data);
+		break;
+	case BINARY_LITERAL_DEFLATED:
+		free(desc->buffer);
+		desc->buffer = data;
+		dst_size = patch->deflate_origlen;
+		break;
+	}
+	if (!desc->buffer)
+		return -1;
+	desc->size = desc->alloc = dst_size;
+	return 0;
+}
+
 static int apply_binary(struct buffer_desc *desc, struct patch *patch)
 {
 	const char *name = patch->old_name ? patch->old_name : patch->new_name;
@@ -1466,18 +1542,20 @@ static int apply_binary(struct buffer_de
 				     "'%s' but it is not empty", name);
 	}
 
-	if (desc->buffer) {
+	get_sha1_hex(patch->new_sha1_prefix, sha1);
+	if (!memcmp(sha1, null_sha1, 20)) {
 		free(desc->buffer);
 		desc->alloc = desc->size = 0;
-	}
-	get_sha1_hex(patch->new_sha1_prefix, sha1);
-	if (!memcmp(sha1, null_sha1, 20))
+		desc->buffer = NULL;
 		return 0; /* deletion patch */
+	}
 
 	if (has_sha1_file(sha1)) {
+		/* We already have the postimage */
 		char type[10];
 		unsigned long size;
 
+		free(desc->buffer);
 		desc->buffer = read_sha1_file(sha1, type, &size);
 		if (!desc->buffer)
 			return error("the necessary postimage %s for "
@@ -1486,28 +1564,13 @@ static int apply_binary(struct buffer_de
 		desc->alloc = desc->size = size;
 	}
 	else {
-		char type[10];
-		unsigned long src_size, dst_size;
-		void *src;
-
-		get_sha1_hex(patch->old_sha1_prefix, sha1);
-		src = read_sha1_file(sha1, type, &src_size);
-		if (!src)
-			return error("the necessary preimage %s for "
-				     "'%s' cannot be read",
-				     patch->old_sha1_prefix, name);
-
-		/* patch->fragment->patch has the delta data and
-		 * we should apply it to the preimage.
+		/* We have verified desc matches the preimage;
+		 * apply the patch data to it, which is stored
+		 * in the patch->fragments->{patch,size}.
 		 */
-		desc->buffer = patch_delta(src, src_size,
-					   (void*) patch->fragments->patch,
-					   patch->fragments->size,
-					   &dst_size);
-		if (!desc->buffer)
+		if (apply_binary_fragment(desc, patch))
 			return error("binary patch does not apply to '%s'",
 				     name);
-		desc->size = desc->alloc = dst_size;
 
 		/* verify that the result matches */
 		write_sha1_file_prepare(desc->buffer, desc->size, blob_type,
@@ -2102,7 +2165,8 @@ int main(int argc, char **argv)
 			diffstat = 1;
 			continue;
 		}
-		if (!strcmp(arg, "--allow-binary-replacement")) {
+		if (!strcmp(arg, "--allow-binary-replacement") ||
+		    !strcmp(arg, "--binary")) {
 			allow_binary_replacement = 1;
 			continue;
 		}
diff --git a/cache.h b/cache.h
index 2f32f3d..4b7a439 100644
--- a/cache.h
+++ b/cache.h
@@ -365,5 +365,6 @@ extern void setup_pager(void);
 
 /* base85 */
 int decode_85(char *dst, char *line, int linelen);
+void encode_85(char *buf, unsigned char *data, int bytes);
 
 #endif /* CACHE_H */
diff --git a/diff.c b/diff.c
index b14d897..94bd94a 100644
--- a/diff.c
+++ b/diff.c
@@ -392,78 +392,75 @@ static void show_stats(struct diffstat_t
 			total_files, adds, dels);
 }
 
-static void *encode_delta_size(void *data, unsigned long size)
+static unsigned char *deflate_it(char *data,
+				 unsigned long size,
+				 unsigned long *result_size)
 {
-	unsigned char *cp = data;
-	*cp++ = size;
-	size >>= 7;
-	while (size) {
-		cp[-1] |= 0x80;
-		*cp++ = size;
-		size >>= 7;
-	}
-	return cp;
-}
-
-static void *safe_diff_delta(const unsigned char *src, unsigned long src_size,
-			     const unsigned char *dst, unsigned long dst_size,
-			     unsigned long *delta_size)
-{
-	unsigned long bufsize;
-	unsigned char *data;
-	unsigned char *cp;
-
-	if (src_size && dst_size)
-		return diff_delta(src, src_size, dst, dst_size, delta_size, 0);
-
-	/* diff-delta does not like to do delta with empty, so
-	 * we do that by hand here.  Sigh...
-	 */
-
-	if (!src_size)
-		/* literal copy can be done only 127-byte at a time.
-		 */
-		bufsize = dst_size + (dst_size / 127) + 40;
-	else
-		bufsize = 40;
-	data = xmalloc(bufsize);
-	cp = encode_delta_size(data, src_size);
-	cp = encode_delta_size(cp, dst_size);
-
-	if (dst_size) {
-		/* copy out literally */
-		while (dst_size) {
-			int sz = (127 < dst_size) ? 127 : dst_size;
-			*cp++ = sz;
-			dst_size -= sz;
-			while (sz) {
-				*cp++ = *dst++;
-				sz--;
-			}
-		}
-	}
-	*delta_size = (cp - data);
-	return data;
+	int bound;
+	unsigned char *deflated;
+	z_stream stream;
+
+	memset(&stream, 0, sizeof(stream));
+	deflateInit(&stream, Z_BEST_COMPRESSION);
+	bound = deflateBound(&stream, size);
+	deflated = xmalloc(bound);
+	stream.next_out = deflated;
+	stream.avail_out = bound;
+
+	stream.next_in = (unsigned char *)data;
+	stream.avail_in = size;
+	while (deflate(&stream, Z_FINISH) == Z_OK)
+		; /* nothing */
+	deflateEnd(&stream);
+	*result_size = stream.total_out;
+	return deflated;
 }
 
 static void emit_binary_diff(mmfile_t *one, mmfile_t *two)
 {
-	void *delta, *cp;
+	void *cp;
+	void *delta;
+	void *deflated;
+	void *data;
+	unsigned long orig_size;
 	unsigned long delta_size;
+	unsigned long deflate_size;
+	unsigned long data_size;
 
 	printf("GIT binary patch\n");
-	delta = safe_diff_delta(one->ptr, one->size,
-				two->ptr, two->size,
-				&delta_size);
-	if (!delta)
-		die("unable to generate binary diff");
-
-	/* emit delta encoded in base85 */
-	cp = delta;
-	while (delta_size) {
-		int bytes = (52 < delta_size) ? 52 : delta_size;
+	/* We could do deflated delta, or we could do just deflated two,
+	 * whichever is smaller.
+	 */
+	delta = NULL;
+	deflated = deflate_it(two->ptr, two->size, &deflate_size);
+	if (one->size && two->size) {
+		delta = diff_delta(one->ptr, one->size,
+				   two->ptr, two->size,
+				   &delta_size, deflate_size);
+		orig_size = delta_size;
+		if (delta)
+			delta = deflate_it(delta, delta_size, &delta_size);
+	}
+
+	if (delta && delta_size < deflate_size) {
+		printf("delta %lu\n", orig_size);
+		free(deflated);
+		data = delta;
+		data_size = delta_size;
+	}
+	else {
+		printf("literal %lu\n", two->size);
+		free(delta);
+		data = deflated;
+		data_size = deflate_size;
+	}
+
+	/* emit data encoded in base85 */
+	cp = data;
+	while (data_size) {
+		int bytes = (52 < data_size) ? 52 : data_size;
 		char line[70];
-		delta_size -= bytes;
+		data_size -= bytes;
 		if (bytes <= 26)
 			line[0] = bytes + 'A' - 1;
 		else
@@ -473,7 +470,7 @@ static void emit_binary_diff(mmfile_t *o
 		puts(line);
 	}
 	printf("\n");
-	free(delta);
+	free(data);
 }
 
 #define FIRST_FEW_BYTES 8000
@@ -538,7 +535,11 @@ static void builtin_diff(const char *nam
 		die("unable to read files to diff");
 
 	if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2)) {
-		if (o->full_index)
+		/* Quite common confusing case */
+		if (mf1.size == mf2.size &&
+		    !memcmp(mf1.ptr, mf2.ptr, mf1.size))
+			goto free_ab_and_return;
+		if (o->binary)
 			emit_binary_diff(&mf1, &mf2);
 		else
 			printf("Binary files %s and %s differ\n",
@@ -1239,6 +1240,10 @@ int diff_opt_parse(struct diff_options *
 		options->rename_limit = strtoul(arg+2, NULL, 10);
 	else if (!strcmp(arg, "--full-index"))
 		options->full_index = 1;
+	else if (!strcmp(arg, "--binary")) {
+		options->output_format = DIFF_FORMAT_PATCH;
+		options->full_index = options->binary = 1;
+	}
 	else if (!strcmp(arg, "--name-only"))
 		options->output_format = DIFF_FORMAT_NAME;
 	else if (!strcmp(arg, "--name-status"))
diff --git a/diff.h b/diff.h
index b3b2c4d..d052608 100644
--- a/diff.h
+++ b/diff.h
@@ -28,6 +28,7 @@ struct diff_options {
 		 with_raw:1,
 		 with_stat:1,
 		 tree_in_recursive:1,
+		 binary:1,
 		 full_index:1,
 		 silent_on_remove:1,
 		 find_copies_harder:1;
-- 
1.3.1.g25a9

^ permalink raw reply related

* Re: [ANNOUNCE] Git wiki
From: Junio C Hamano @ 2006-05-05  9:51 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20060505092332.GY27689@pasky.or.cz>

Petr Baudis <pasky@suse.cz> writes:

> But the non-obviously important part here to note is that the branch B
> merely "corrects a typo on a comment somewhere" - the latest versions in
> branch A and branch B are always compared for renames, therefore if
> branch A renamed the file and branch B sums up to some larger-scale
> changes in the file, it still won't be merged properly.

I probably am guilty of starting this misinformation, but the
code does not compare the latest in A and B for rename
detection; it compares (O, A) and (O, B).

But the end result is the same - what you say is correct.  If a
path (say O to A) that renamed has too big a change, then no
matter how small the changes are on the other path (O to B),
rename detection can be fooled.  We could perhaps alleviate it
by following the whole commit chain.

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Petr Baudis @ 2006-05-05  9:23 UTC (permalink / raw)
  To: Fredrik Kuivinen; +Cc: linux, git
In-Reply-To: <20060505062236.GA4544@c165.ib.student.liu.se>

Dear diary, on Fri, May 05, 2006 at 08:22:36AM CEST, I got a letter
where Fredrik Kuivinen <freku045@student.liu.se> said that...
> On Thu, May 04, 2006 at 08:56:59PM -0400, linux@horizon.com wrote:
> > What people who are asking for explicit rename tracking actually want
> > is automatic rename merging.  If branch A renames a file, and branch B
> > corrects a typo on a comment somewhere, they'd like the merge to
> > both patch and rename the file.  If you can do that, you have met the
> > need, even if your solution isn't the one the feature requester
> > imagined.
> 
> I don't know if you already know this, if you do it might be valuable
> for other readers.
> 
> If the rename is detected by the current rename detection code
> (git-diff-tree -M) then the merge case described above is handled
> perfectly fine by the current git. That is, the rename is followed and
> the patch fixing the typo is applied to the renamed file. This assumes
> that the default merge strategy (recursive) is used.

But the non-obviously important part here to note is that the branch B
merely "corrects a typo on a comment somewhere" - the latest versions in
branch A and branch B are always compared for renames, therefore if
branch A renamed the file and branch B sums up to some larger-scale
changes in the file, it still won't be merged properly.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Right now I am having amnesia and deja-vu at the same time.  I think
I have forgotten this before.

^ permalink raw reply

* Re: [PATCH] Fix linking with OpenSSL
From: Junio C Hamano @ 2006-05-05  8:02 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: git
In-Reply-To: <20060505075754.GA7237@mipter.zuzino.mipt.ru>

Alexey Dobriyan <adobriyan@gmail.com> writes:

> It does. It also crashes busybox patch applet. Oh, well...

Could you elaborate on "busybox patch" problem?

^ permalink raw reply

* Re: [PATCH] Fix linking with OpenSSL
From: Alexey Dobriyan @ 2006-05-05  7:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vslnp2y5x.fsf@assigned-by-dhcp.cox.net>

On Thu, May 04, 2006 at 04:00:26PM -0700, Junio C Hamano wrote:
> Junio C Hamano <junkio@cox.net> writes:
> > Alexey Dobriyan <adobriyan@gmail.com> writes:
> >> For those who put it into interesting (read: default) place.
> >>
> >> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
> >>
> >> --- a/Makefile
> >> +++ b/Makefile
> >> @@ -559,7 +559,7 @@ git-http-push$X: revision.o http.o http-
> >>  
> >>  git-rev-list$X: rev-list.o $(LIB_FILE)
> >>  	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
> >> -		$(LIBS) $(OPENSSL_LIBSSL)
> >> +		$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
> >>  
> >>  init-db.o: init-db.c
> >>  	$(CC) -c $(ALL_CFLAGS) \
> >
> > We used to depend on bignum from openssl for rev-list
> > (merge-order), and if I remember correctly that was the only
> > reason built recipe for rev-list is different from other
> > programs.  I wonder if we can just get rid of this thing, and
> > have it built with git-%$X rule like everybody else.
> >
> > Can somebody try that out and report what happens?
> 
> Well, I did.  Alexey, does this work for you?

It does. It also crashes busybox patch applet. Oh, well...

> --- a/Makefile
> +++ b/Makefile
> @@ -564,10 +564,6 @@ git-http-push$X: revision.o http.o http-
>  	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
>  		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
>  
> -git-rev-list$X: rev-list.o $(LIB_FILE)
> -	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
> -		$(LIBS) $(OPENSSL_LIBSSL)
> -
>  init-db.o: init-db.c
>  	$(CC) -c $(ALL_CFLAGS) \
>  		-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c

^ permalink raw reply

* Re: [PATCH] binary patch.
From: Junio C Hamano @ 2006-05-05  6:47 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0605042241240.28543@localhost.localdomain>

Nicolas Pitre <nico@cam.org> writes:

> On Thu, 4 May 2006, Junio C Hamano wrote:
>
>> This adds "binary patch" to the diff output and teaches apply
>> what to do with them.
>
> This is nice.
>
> However I'd deflate the delta data before encoding it with base85.

Yeah, things still to be done are deflating both delta and
optionally perhaps use just deflate without delta for "new file"
codepath.

And testsuite.

^ permalink raw reply

* Re: [ANNOUNCE] Git wiki
From: Jakub Narebski @ 2006-05-05  6:26 UTC (permalink / raw)
  To: git
In-Reply-To: <20060505062236.GA4544@c165.ib.student.liu.se>

Fredrik Kuivinen wrote:

> On Thu, May 04, 2006 at 08:56:59PM -0400, linux@horizon.com wrote:
>> What people who are asking for explicit rename tracking actually want
>> is automatic rename merging.  If branch A renames a file, and branch B
>> corrects a typo on a comment somewhere, they'd like the merge to
>> both patch and rename the file.  If you can do that, you have met the
>> need, even if your solution isn't the one the feature requester
>> imagined.
> 
> I don't know if you already know this, if you do it might be valuable
> for other readers.
> 
> If the rename is detected by the current rename detection code
> (git-diff-tree -M) then the merge case described above is handled
> perfectly fine by the current git. That is, the rename is followed and
> the patch fixing the typo is applied to the renamed file. This assumes
> that the default merge strategy (recursive) is used.

And if you do 'commit - rename, no changes - commit' sequence then rename
will be detected. 

-- 
Jakub Narebski
Warsaw, Poland

^ permalink raw reply


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