Git development
 help / color / mirror / Atom feed
* Re: git am and CRLF files
From: Daniele Segato @ 2009-11-30 12:06 UTC (permalink / raw)
  To: kusmabite; +Cc: Nanako Shiraishi, Stefan Naewe, git@vger.kernel.org
In-Reply-To: <40aa078e0911160343k41393197s56d26576bcbfbe90@mail.gmail.com>

On Mon, Nov 16, 2009 at 12:43 PM, Erik Faye-Lund
<kusmabite@googlemail.com> wrote:
> According to RFC 5322, email messages use CRLF as the
> newline-sequence. In order to be able to distinguish between CRLF and
> LF in an e-mail patch, the message needs to be use some
> transfer-encoding that preserves newline style (like base64).
>
> Perhaps this would be better fixed by having format-patch (or prehaps
> the MUA ?) base64-encode the message body if the file contains
> non-LF-newlines, and normalizing CRLF to LF before transport-decoding?
> Or does some MUAs transport-decode before storing the message to disk?
>
> I realize this might make it a bit tricky to review patches that
> contains CRLF-newlines before mailing them out, but perhaps inspecting
> the format-patch output is the wrong place to do this?


why don't adding that information in the mail header?
or may be made format-patch create a "comment line" with that information?

if that line is missing it could keep the default behavior (what it
did until now)

^ permalink raw reply

* git archive without path
From: Dmitry Potapov @ 2009-11-30 12:32 UTC (permalink / raw)
  To: git

Hi!

I have never run "git archive" inside of a subdirectory but somehow I
have always assumed that it creates an archive containing all files in
it regardless the current directory. In fact, the git-archive man page
says so:

path
    If one or more paths are specified, include only these in the
    archive, otherwise include all files and subdirectories.


But it turned out that "git archive" works as "git archive .", i.e.
adds files starting with the current directory. Is any rational for
this behavior? It smells to me like a bug rather than a feature. I
cannot imagine wanting to create archive containing just part of the
whole repository just because he happened to be in that directory,
and documentation clearly says that all files should be added unless
one or more paths are specified.


Dmitry

^ permalink raw reply

* Re: [RFC/PATCH] t7011: Mark fixed test as such
From: Michael J Gruber @ 2009-11-30 12:49 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: git, Junio C Hamano
In-Reply-To: <fcaeb9bf0911291756g1857fe32r8da8e50f0a137119@mail.gmail.com>

Nguyen Thai Ngoc Duy venit, vidit, dixit 30.11.2009 02:56:
> On Sun, Nov 29, 2009 at 8:57 PM, Michael J Gruber
> <git@drmicha.warpmail.net> wrote:
>> Nguyen Thai Ngoc Duy venit, vidit, dixit 29.11.2009 09:47:
>>> On 11/29/09, Michael J Gruber <git@drmicha.warpmail.net> wrote:
>>>> Test 16/17 had been fixed since its introduction in b4d1690 (Teach Git
>>>>  to respect skip-worktree bit (reading part), 2009-08-20). So, mark it as
>>>>  expect_success rather than expect_failure.
>>>>
>>>>  Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
>>>
>>> No ACK. See below.
>>>
>>>>  ---
>>>>  I'm actually wondering about 17/17 as well.
>>>>  If commit is called with a file name then shouldn't it simply commit the
>>>>  current state of the file in the worktree, no matter what the index or
>>>>  skip-worktree say? I therefore think 17/17 should be expect_success
>>>>  and have no test_must_fail.
>>>
>>> Both 16/17 and 17/17 ensure that Git won't look at files on worktree
>>> if they are marked as skip-worktree (by definition of skip-worktree,
>>> you can safely ignore worktree, otherwise you would not mark them as
>>> such). 16/17 happens to pass, not because it does not touch worktree,
>>> but because the base index does not have "1", which happens to is the
>>> same situation in 16/17 (test commit when "1" is gone). The result is
>>> OK but it is actually not (17/17 shows this clearer as it commits the
>>> worktree version).
>>
>> On 16/17, I really cannot agree. You explain that you expect the test to
>> succeed (we agree here), but that it succeeds for the wrong reasons. So
>> it should be either "expect_success", or the test itself should be
>> changed so that it really tests what it intends to, otherwise it raises
>> a wrong "FIXED". I suggested and submitted the former.
> 
> That was my bad in setting up the environment for 16/17. I will fix
> that in the next roll of nd/sparse.
> 
>> On 17/17, it's not clear what should happen. "skip-worktree" says ignore
>> the worktree and look in the index instead of accessing worktree files.
>> But "git commit file" says ignore the index and stage and commit the
>> file from the worktree directly. And that is exactly what happens:
>>
>> You say "git commit file".
>> That means "ignore the index".
>> That also means that git ignores the skip-worktree bit which is set in
>> the index.
>> Therefore, file is committed with the content is has in the worktree.
> 
> To me, no command should break out skip-worktree mask. In reality I
> would expect that case 17/17 only happens when a user accidentally
> leaves a file that is marked skip-worktree and tries to commit it. An
> error would be more appropriate to keep consistency with other
> commands ("git diff HEAD -- 1" would show nothing before committing),
> and to warn the user that he/she is stepping on the border. He/she can
> then choose to extend worktree area if still wants to commit that
> file. How does that sound?
> 
>> I'm going by the documentation for git-update-index and git-commit. It
>> could be that they are wrong, too, but they agree with the code, so
>> what's the reference for saying both code and documentation are wrong?
> 
> Both code and documentation are for Git without skip-worktree. If you
> agree with my reasoning above, I will update documentation to reflect
> this too.

Thanks for the clarification. I see the background behind 17/17 now. I
think git-commit.txt needs a careful update then, because the
explanation of a common feature (git commit file) should not get
confusing because of a not so common feature (skip-worktree/sparse co).

Regarding 16/17: Seeing a FIXED is very misleading. I caught it during
my work on a patch series and was confused. FIXED usually occurs only
while working on a fix, before adjusting the test. So, unless the reroll
of nd/sparse is to happen very soon, I still suggest marking it as
expect_success as proposed, and then modifying the test during the reroll.

Cheers,
Michael

^ permalink raw reply

* Re: git am and CRLF files
From: Ismael Luceno @ 2009-11-30 12:50 UTC (permalink / raw)
  To: Daniele Segato; +Cc: git
In-Reply-To: <9accb4400911300406l592306c8t889c28ba7b48674b@mail.gmail.com>

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

Daniele Segato escribió:
> On Mon, Nov 16, 2009 at 12:43 PM, Erik Faye-Lund
> <kusmabite@googlemail.com> wrote:
>> According to RFC 5322, email messages use CRLF as the
>> newline-sequence. In order to be able to distinguish between CRLF and
>> LF in an e-mail patch, the message needs to be use some
>> transfer-encoding that preserves newline style (like base64).
>>
>> Perhaps this would be better fixed by having format-patch (or prehaps
>> the MUA ?) base64-encode the message body if the file contains
>> non-LF-newlines, and normalizing CRLF to LF before transport-decoding?
>> Or does some MUAs transport-decode before storing the message to disk?
>>
>> I realize this might make it a bit tricky to review patches that
>> contains CRLF-newlines before mailing them out, but perhaps inspecting
>> the format-patch output is the wrong place to do this?
> 
> 
> why don't adding that information in the mail header?
> or may be made format-patch create a "comment line" with that information?
> 
> if that line is missing it could keep the default behavior (what it
> did until now)
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

It would make more sense to simply use MIME attachments...

-- 
Ismael Luceno


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: git archive without path
From: Michael J Gruber @ 2009-11-30 13:05 UTC (permalink / raw)
  To: Dmitry Potapov; +Cc: git
In-Reply-To: <20091130123203.GA11235@dpotapov.dyndns.org>

Dmitry Potapov venit, vidit, dixit 30.11.2009 13:32:
> Hi!
> 
> I have never run "git archive" inside of a subdirectory but somehow I
> have always assumed that it creates an archive containing all files in
> it regardless the current directory. In fact, the git-archive man page
> says so:
> 
> path
>     If one or more paths are specified, include only these in the
>     archive, otherwise include all files and subdirectories.
> 
> 
> But it turned out that "git archive" works as "git archive .", i.e.
> adds files starting with the current directory. Is any rational for
> this behavior? It smells to me like a bug rather than a feature. I
> cannot imagine wanting to create archive containing just part of the
> whole repository just because he happened to be in that directory,
> and documentation clearly says that all files should be added unless
> one or more paths are specified.

Depends on the definition of "all" :)

In fact: Two mighty powers are fighting right now for the primacy in the
Land of the Git, and both carry the name "consistency" on their flags.
One is the "order of the consistency of generations", also named
"backwards compatibility", and one is the "order of the consistency of
commands", also named "user experience".

Many commands have different defaults with respect to how they behave in
a subdirectory (compare status to ls-files, e.g.), and the discussion
about how to best change that are underway, most prominently in the case
of git grep. I expect that we'll have a gradual migration path towards a
"full-tree" default, but that is just my personal interpretation of the
current "battle". In the short term the best that we can hope for is a
consistent, convenient notation which enforcers a specific behaviour,
such as "/" (non-existent) versus "." (existent).

Cheers,
Michael

^ permalink raw reply

* [PATCH] Add --track option to git clone
From: David Soria Parra @ 2009-11-30 13:16 UTC (permalink / raw)
  To: git

The following series adds a --track option to git clone. If the --track option
is specified only the given remote branch will be received and checked out.

It tries to make the following usecase possible:
Imagine you are working on a project that has 1.x and a 2.x branch. The project
itself requires a complex setup (webserver, configuration files, etc). Setting up
1.x and 2.x branch requires a lot of work, but a developer needs to maintain both.
He'll use the --track option to clone the 2.x branch into a directory and does the same
with the 1.x branch, where he setup the project. He can use locally separate repositories
while still being able to push to just one remote repository.

I'm aware that it's not possible to give more than one --track option. Implementing
the possibility to specify multiple --track option would certainly a good improvment
later, but would also require a lot more work as far as I understand the clone code.

Being able to specify just one --track option is a compromise of doing a small change
and implementing this feature.

^ permalink raw reply

* [PATCH 1/2] Teach clone to clone just one remote branch using --track
From: David Soria Parra @ 2009-11-30 13:16 UTC (permalink / raw)
  To: git; +Cc: David Soria Parra
In-Reply-To: <1259587004-14633-1-git-send-email-sn_@gmx.net>

From: David Soria Parra <dsp@php.net>

Add a --track option that can be used to clone just the
given branch from the remote and nothing else. This is done
by setting the remote.<branch>.fetch option before cloning.
This option cannot be used together with --mirror.
For example using

    git clone --track next git://git.kernel.org/pub/scm/git/git.git

will just clone the next branch from the git.git repository.

The option is called --track to ensure clean wording with
'git remote add --track'.

Signed-off-by: David Soria Parra <dsp@php.net>
---
 builtin-clone.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/builtin-clone.c b/builtin-clone.c
index 5df8b0f..bc335ee 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -43,6 +43,7 @@ static char *option_template, *option_reference, *option_depth;
 static char *option_origin = NULL;
 static char *option_branch = NULL;
 static char *option_upload_pack = "git-upload-pack";
+static char *option_track = NULL;
 static int option_verbose;
 
 static struct option builtin_clone_options[] = {
@@ -76,6 +77,8 @@ static struct option builtin_clone_options[] = {
 		   "path to git-upload-pack on the remote"),
 	OPT_STRING(0, "depth", &option_depth, "depth",
 		    "create a shallow clone of that depth"),
+	OPT_STRING('t', "track", &option_track, "branch",
+			"remote branche to track"),
 
 	OPT_END()
 };
@@ -483,7 +486,14 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
 	}
 
-	strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
+	if (option_track) {
+		if (option_mirror)
+			return error("Cannot use --track together with --mirror");
+		strbuf_addf(&value, "+%s%s:%s%s", src_ref_prefix, option_track, branch_top.buf, option_track);
+		option_branch = option_track;
+	} else {
+		strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
+	}
 
 	if (option_mirror || !option_bare) {
 		/* Configure the remote */
-- 
1.6.6.rc0.268.g1c272

^ permalink raw reply related

* [PATCH 2/2] Documentation: Add --track option to the git clone manpage
From: David Soria Parra @ 2009-11-30 13:16 UTC (permalink / raw)
  To: git; +Cc: David Soria Parra
In-Reply-To: <1259587004-14633-1-git-send-email-sn_@gmx.net>

From: David Soria Parra <dsp@php.net>

Signed-off-by: David Soria Parra <dsp@php.net>
---
 Documentation/git-clone.txt |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 7e7d9fc..3c2e1b8 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -12,7 +12,7 @@ SYNOPSIS
 'git clone' [--template=<template_directory>]
 	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
 	  [-o <name>] [-u <upload-pack>] [--reference <repository>]
-	  [--depth <depth>] [--recursive] [--] <repository> [<directory>]
+	  [-t <name>] [--depth <depth>] [--recursive] [--] <repository> [<directory>]
 
 DESCRIPTION
 -----------
@@ -135,6 +135,12 @@ objects from the source repository into a pack in the cloned repository.
 	instead. In a non-bare repository, this is the branch that will
 	be checked out.
 
+--track <name>::
+-t <name>::
+	Instead of cloning the complete remote repository, only the given
+	remote branch `<name>` will be tracked and checked out.
+	This implies --branch `<name>`.
+
 --upload-pack <upload-pack>::
 -u <upload-pack>::
 	When given, and the repository to clone from is accessed
-- 
1.6.6.rc0.268.g1c272

^ permalink raw reply related

* Re: [RFC/PATCH] t7011: Mark fixed test as such
From: Nguyen Thai Ngoc Duy @ 2009-11-30 13:18 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: git, Junio C Hamano
In-Reply-To: <4B13BF3D.7010503@drmicha.warpmail.net>

On 11/30/09, Michael J Gruber <git@drmicha.warpmail.net> wrote:
>  Regarding 16/17: Seeing a FIXED is very misleading. I caught it during
>  my work on a patch series and was confused. FIXED usually occurs only
>  while working on a fix, before adjusting the test. So, unless the reroll
>  of nd/sparse is to happen very soon, I still suggest marking it as
>  expect_success as proposed, and then modifying the test during the reroll.

I won't work on it until this weekend. If you insist, then better put
command "true" after test_must_fail to indicate that the test is
broken (could be line-wrapped by gmail, but it's simple enough to
recreate)

diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh
index e996928..da8dcbb 100755
--- a/t/t7011-skip-worktree-reading.sh
+++ b/t/t7011-skip-worktree-reading.sh
@@ -152,6 +152,7 @@ test_expect_failure 'commit on skip-worktree
absent entries' '
 	git reset &&
 	setup_absent &&
 	test_must_fail git commit -m null 1
+	true
 '

 test_expect_failure 'commit on skip-worktree dirty entries' '
-- 
Duy

^ permalink raw reply related

* [PATCH] Documentation: Document --branch option in git clone synopsis
From: David Soria Parra @ 2009-11-30 13:27 UTC (permalink / raw)
  To: git; +Cc: David Soria Parra

From: David Soria Parra <dsp@php.net>

Document the --branch option as [-b <name>] in git clones synopsis.

Signed-off-by: David Soria Parra <dsp@php.net>
---
 Documentation/git-clone.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 7e7d9fc..7ccd742 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -11,7 +11,7 @@ SYNOPSIS
 [verse]
 'git clone' [--template=<template_directory>]
 	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
-	  [-o <name>] [-u <upload-pack>] [--reference <repository>]
+	  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
 	  [--depth <depth>] [--recursive] [--] <repository> [<directory>]
 
 DESCRIPTION
-- 
1.6.6.rc0.268.g1c272

^ permalink raw reply related

* Re: [PATCH] Add --track option to git clone
From: Michael J Gruber @ 2009-11-30 13:36 UTC (permalink / raw)
  To: David Soria Parra; +Cc: git
In-Reply-To: <1259587004-14633-1-git-send-email-sn_@gmx.net>

David Soria Parra venit, vidit, dixit 30.11.2009 14:16:
> The following series adds a --track option to git clone. If the --track option
> is specified only the given remote branch will be received and checked out.
> 
> It tries to make the following usecase possible:
> Imagine you are working on a project that has 1.x and a 2.x branch. The project
> itself requires a complex setup (webserver, configuration files, etc). Setting up
> 1.x and 2.x branch requires a lot of work, but a developer needs to maintain both.
> He'll use the --track option to clone the 2.x branch into a directory and does the same
> with the 1.x branch, where he setup the project. He can use locally separate repositories
> while still being able to push to just one remote repository.

While I think the feature itself is useful, I don't think it's that
useful for the case you mention. If you clone all branches anyways
you're much better of using alternates or --reference, or the workdir
script in contrib/

> I'm aware that it's not possible to give more than one --track option. Implementing
> the possibility to specify multiple --track option would certainly a good improvment
> later, but would also require a lot more work as far as I understand the clone code.
> 
> Being able to specify just one --track option is a compromise of doing a small change
> and implementing this feature.

That restriction makes a lot of sense. Two suggestions:

- How does one turn such a "partial" clone into a full one? That should
be documented somewhere (git config remote.origin.fetch
'+refs/heads/*:refs/remotes/origin/*').

- A test would be nice, which makes sure you clone what you think you clone.

Cheers,
Michael

^ permalink raw reply

* equal-tree-merges as way to make rebases fast-forward-able
From: Bernhard R. Link @ 2009-11-30 14:43 UTC (permalink / raw)
  To: git

The itch this idea is supposed to scratch is the problem that a rebase
or a amended commit is no longer a fast-forward, so cannot be easily
pulled.
While this is not a problem in most workflows, as one can either merge
or keep everything private and rebase until published, it would be nice
to have a way for cases in between, where both a clean presentable
commit order is to be maintained and people (or yourself from different
repositories) should be able to easily upgrade to newer versions without
an error-prone not-fast-forward.

My idea to solve this is combining both histories, the rebased/revised
history and the actualy history, marking with some "equal-tree-merge"
the point where they have the same result.
The following mails show some patches to implement this by means of
a merge where all parents have the same tree and some special casing
when encountering such a thing. This has the advantage that older git
version will just see strange merges and may present both histories,
but otherwise just work.

Example 1:

Let's assume you maintain such a regularily-rebased branch that you
want to be able to publish (or pull from other repositories for example
on your laptop):

o=m=o=o=master
   \
    a=b=c=d=e=feature

with this patch you can do "git rebase -eqt master" and get:

              a'=b'=c'=d'=e'=feature'=eqt
             /                       /
o=m=o=o=master--------              /
   \                  \            /
    a=b=c=d=e=feature--merge-------

i.e: the new feature branch has both histories:
  - "feature'" where everything is cleanly rebased and in a form where
               format-patch is suitable to send it upstream
  - "merge" which is both a descendant from feature (so one can see what
    changed since that time and can just pull when one had had cloned feature)

Example 2:

Let's assume you have a feature branch like

o=master
   \
    a=b=c=d=e=f

Assume you just commited "f" which fixes a bug introduced by "b".
Now you of course do not want to send it that way upstream (as it will
make reviewing harder, may force people bisecting to skip some versions
every time they hit this region and so on), so you want to
bisect -i and squash "f" into "b".

o=master
   \
    a=b+f=c'=d'=e'

But if you had already cloned at state "d" to your laptop (or made a backup
of that branch at some server, or published it for use of some collegues)
it will not be a fast-forward, so you have to be very carefull to not
accidentially lose a commit that is already there.

So with this patches you can do "git rebase -i --eqt" and squash f into b
and get:

o=master
   \
    a=b=c=d=e=f---
     \            \
      b+f=c'=d'=e'=eqt

which means that you can just pull from your laptop and get the new head
as fast-forward, but still have a proper history ready for submitting.

The only downsize of this approach is that an unpatched/old git of course
does not know about that it can just choose one of both histories but think
it has to look at both, so git-format-patch will return patches multiple times
and git-rebase will also try to apply both branches, which the patched version
no longer does, only showing the 'presentable' in this case.

Those patches are a bit rough and mostly intended to show how it could work
and to allow experimenting with it. I think the biggest thing still missing
(apart from documentation, error handling, better commit messages) is making
git bisect take advantage of this and only looking at the nice branch.

Bernhard R. Link (7):
  add new command git equal-tree-marker
  add option to only visit the first parent of a equal tree merge
  format-patch defaults to --first-equal-tree-only
  support equal tree merges in interactive rebase
  make rebase -m equal tree marker aware
  add support for creating equal tree markers after rebase
  add support for creating equal tree markers to rebase -i

 .gitignore                 |    1 +
 Makefile                   |    1 +
 builtin-log.c              |    1 +
 git-equal-tree-marker.sh   |   50 ++++++++++++++++++++++++++++++++++++++
 git-rebase--interactive.sh |   33 +++++++++++++++++++++++++
 git-rebase.sh              |   35 ++++++++++++++++++++++++--
 revision.c                 |   57 +++++++++++++++++++++++++++++++++++++-------
 revision.h                 |    1 +
 8 files changed, 167 insertions(+), 12 deletions(-)
 create mode 100644 git-equal-tree-marker.sh

Hochachtungsvoll,
	Bernhard R. Link
-- 
"Never contain programs so few bugs, as when no debugging tools are available!"
	Niklaus Wirth

^ permalink raw reply

* [PATCH 1/7] add new command git equal-tree-marker
From: Bernhard R. Link @ 2009-11-30 14:43 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

This adds a new commit denoting tha current branch has the same
tree as another branch, thus allowing fast-forward from the named
commits to this one.

TODO: manpage, rewrite as builtin once the semantics are accepted?
---
 .gitignore               |    1 +
 Makefile                 |    1 +
 git-equal-tree-marker.sh |   50 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 0 deletions(-)
 create mode 100644 git-equal-tree-marker.sh

diff --git a/.gitignore b/.gitignore
index ac02a58..248d146 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@
 /git-difftool
 /git-difftool--helper
 /git-describe
+/git-equal-tree-marker
 /git-fast-export
 /git-fast-import
 /git-fetch
diff --git a/Makefile b/Makefile
index 4dba10e..913d4c4 100644
--- a/Makefile
+++ b/Makefile
@@ -336,6 +336,7 @@ TEST_PROGRAMS =
 SCRIPT_SH += git-am.sh
 SCRIPT_SH += git-bisect.sh
 SCRIPT_SH += git-difftool--helper.sh
+SCRIPT_SH += git-equal-tree-marker.sh
 SCRIPT_SH += git-filter-branch.sh
 SCRIPT_SH += git-lost-found.sh
 SCRIPT_SH += git-merge-octopus.sh
diff --git a/git-equal-tree-marker.sh b/git-equal-tree-marker.sh
new file mode 100644
index 0000000..403cc56
--- /dev/null
+++ b/git-equal-tree-marker.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Bernhard R. Link
+#
+# Create a new commit making HEAD parent of the arguments,
+# which must be commits with the same tree.
+
+set -e
+
+USAGE='<head>...'
+LONG_USAGE='Make current HEAD parent of the given heads (which need to have the same tree).'
+SUBDIRECTORY_OK=Yes
+OPTIONS_SPEC=
+. git-sh-setup
+cd_to_toplevel
+
+# is there really no function for this?
+tree_of_commit() {
+	git cat-file commit "$1" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'
+}
+
+head="$(git rev-parse --verify HEAD)"
+htree="$(tree_of_commit $head)"
+parents=""
+while test $# -gt 0
+do
+	case "$1" in
+	-h|--h|--he|--hel|--help)
+		usage
+		;;
+	*)
+		h="$(git rev-parse --verify $1)"
+		tree="$(tree_of_commit "$h")"
+		if test "x${htree}" != "x${tree}" ; then
+			echo "Tree of $h is not the same as tree of $head" >&2
+			exit 1
+		fi
+		parents="$parents -p $h"
+		;;
+	esac
+	shift
+done
+
+if test "x$parents" = "x" ; then
+	echo "Not enough arguments!" >&2
+	exit 1
+fi
+
+new_commit="$(echo "Equal tree marker" | git commit-tree "$tree" -p "$head" $parents)"
+git-update-ref HEAD "$new_commit"
-- 
1.6.6.rc0.82.g60a15.dirty

^ permalink raw reply related

* [PATCH 2/7] add option to only visit the first parent of a equal tree merge
From: Bernhard R. Link @ 2009-11-30 14:44 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

rev_info gets a new flag first_equal_tree_only that causes
revision walks to ignore all but the first parent of equal tree
merges.
The default is off and there are options --first-equal-tree-only
and --all-equal-trees to switch it on/off respectively.

TODO:
 - manpage updates
 - check interaction with some of the other options
---
 revision.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 revision.h |    1 +
 2 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/revision.c b/revision.c
index a8a3c3a..fb019d6 100644
--- a/revision.c
+++ b/revision.c
@@ -452,6 +452,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
 	struct commit_list *parent = commit->parents;
 	unsigned left_flag;
 	struct commit_list *cached_base = cache_ptr ? *cache_ptr : NULL;
+	int first_parent_only;
 
 	if (commit->object.flags & ADDED)
 		return 0;
@@ -499,6 +500,21 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
 
 	left_flag = (commit->object.flags & SYMMETRIC_LEFT);
 
+	if (revs->first_parent_only)
+		first_parent_only = 1;
+	else if (revs->first_equal_tree_only && commit->parents) {
+		for (parent = commit->parents; parent; parent = parent->next) {
+			struct commit *p = parent->item;
+
+			if (parse_commit(p) < 0)
+				return -1;
+			if (p->tree != commit->tree)
+				break;
+		}
+		first_parent_only = !parent;
+	} else
+		first_parent_only = 0;
+
 	for (parent = commit->parents; parent; parent = parent->next) {
 		struct commit *p = parent->item;
 
@@ -511,7 +527,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
 			p->object.flags |= SEEN;
 			insert_by_date_cached(p, list, cached_base, cache_ptr);
 		}
-		if (revs->first_parent_only)
+		if (first_parent_only)
 			break;
 	}
 	return 0;
@@ -1067,6 +1083,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		revs->min_age = approxidate(arg + 8);
 	} else if (!strcmp(arg, "--first-parent")) {
 		revs->first_parent_only = 1;
+	} else if (!strcmp(arg, "--first-equal-tree-only")) {
+		revs->first_equal_tree_only = 1;
+	} else if (!strcmp(arg, "--all-equal-trees")) {
+		revs->first_equal_tree_only = 0;
 	} else if (!strcmp(arg, "-g") || !strcmp(arg, "--walk-reflogs")) {
 		init_reflog_walk(&revs->reflog_info);
 	} else if (!strcmp(arg, "--default")) {
@@ -1912,6 +1932,16 @@ static void create_boundary_commit_list(struct rev_info *revs)
 	sort_in_topological_order(&revs->commits, revs->lifo);
 }
 
+static inline void add_boundary_commit(struct rev_info *revs, struct commit *c) {
+	struct object *p = &c->object;
+
+	if (p->flags & (CHILD_SHOWN | SHOWN))
+		return;
+	p->flags |= CHILD_SHOWN;
+	gc_boundary(&revs->boundary_commits);
+	add_object_array(p, NULL, &revs->boundary_commits);
+}
+
 static struct commit *get_revision_internal(struct rev_info *revs)
 {
 	struct commit *c = NULL;
@@ -1987,16 +2017,25 @@ static struct commit *get_revision_internal(struct rev_info *revs)
 	 * 'c', we need to mark its parents that they could be boundaries.
 	 */
 
-	for (l = c->parents; l; l = l->next) {
-		struct object *p;
-		p = &(l->item->object);
-		if (p->flags & (CHILD_SHOWN | SHOWN))
-			continue;
-		p->flags |= CHILD_SHOWN;
-		gc_boundary(&revs->boundary_commits);
-		add_object_array(p, NULL, &revs->boundary_commits);
+	if (revs->first_equal_tree_only && c->parents) {
+		for (l = c->parents; l; l = l->next) {
+			struct commit *p = l->item;
+			parse_commit(p);
+			if (c->tree != p->tree)
+				break;
+		}
+		/* if all parents have the same tree as this node,
+		 * it's an equal tree merge, so ignore all but the
+		 * first parent */
+		if (!l) {
+			add_boundary_commit(revs, c->parents->item);
+			return c;
+		}
 	}
 
+	for (l = c->parents; l; l = l->next) {
+		add_boundary_commit(revs, l->item);
+	}
 	return c;
 }
 
diff --git a/revision.h b/revision.h
index d368003..7ac263c 100644
--- a/revision.h
+++ b/revision.h
@@ -64,6 +64,7 @@ struct rev_info {
 			reverse_output_stage:1,
 			cherry_pick:1,
 			bisect:1,
+			first_equal_tree_only:1,
 			first_parent_only:1;
 
 	/* Diff flags */

^ permalink raw reply related

* [PATCH 3/7] format-patch defaults to --first-equal-tree-only
From: Bernhard R. Link @ 2009-11-30 14:44 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

TODO: manpage update to hint to --all-equal-trees?
---
 builtin-log.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/builtin-log.c b/builtin-log.c
index 33fa6ea..a3a2d3f 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -960,6 +960,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	rev.diff = 1;
 	rev.combine_merges = 0;
 	rev.ignore_merges = 1;
+	rev.first_equal_tree_only = 1;
 	DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
 
 	rev.subject_prefix = fmt_patch_subject_prefix;

^ permalink raw reply related

* [PATCH 4/7] support equal tree merges in interactive rebase
From: Bernhard R. Link @ 2009-11-30 14:44 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

---
 git-rebase--interactive.sh |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0bd3bf7..3da9f3e 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -703,6 +703,7 @@ first and then run 'git rebase --continue' again."
 		fi
 		git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
 			--abbrev=7 --reverse --left-right --topo-order \
+			--first-equal-tree-only \
 			$REVISIONS | \
 			sed -n "s/^>//p" | while read shortsha1 rest
 		do

^ permalink raw reply related

* [PATCH 5/7] make rebase -m equal tree marker aware
From: Bernhard R. Link @ 2009-11-30 14:45 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

---
 git-rebase.sh |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-rebase.sh b/git-rebase.sh
index b121f45..391f6d6 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -539,7 +539,7 @@ echo "$head_name" > "$dotest/head-name"
 echo "$GIT_QUIET" > "$dotest/quiet"
 
 msgnum=0
-for cmt in `git rev-list --reverse --no-merges "$revisions"`
+for cmt in `git rev-list --reverse --first-equal-tree-only --no-merges "$revisions"`
 do
 	msgnum=$(($msgnum + 1))
 	echo "$cmt" > "$dotest/cmt.$msgnum"

^ permalink raw reply related

* [PATCH 6/7] add support for creating equal tree markers after rebase
From: Bernhard R. Link @ 2009-11-30 14:45 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

With the new --eqt option, git rebase adds an equal tree marker,
so that the old branch can be fast-forwarded to the new one.
If the trees are not equal, a fake merge of the new base and the
old branch is created first.

TODO:
 - manpage update,
 - should --eqt have a better (longer more descriptive) name?
 - the commit message of the merge should have a better default
   and presented to the user for editing
---
 git-rebase.sh |   33 +++++++++++++++++++++++++++++++--
 1 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/git-rebase.sh b/git-rebase.sh
index 391f6d6..681c97b 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -50,6 +50,7 @@ diffstat=$(git config --bool rebase.stat)
 git_am_opt=
 rebase_root=
 force_rebase=
+equal_tree_marker=
 
 continue_merge () {
 	test -n "$prev_head" || die "prev_head must be defined"
@@ -132,11 +133,30 @@ call_merge () {
 	esac
 }
 
+# is there really no already existing function for this?
+tree_of_commit() {
+        git cat-file commit "$1" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'
+}
+
 move_to_original_branch () {
 	test -z "$head_name" &&
 		head_name="$(cat "$dotest"/head-name)" &&
 		onto="$(cat "$dotest"/onto)" &&
-		orig_head="$(cat "$dotest"/orig-head)"
+		orig_head="$(cat "$dotest"/orig-head)" &&
+		equal_tree_marker="$(cat "$dotest"/eqt)"
+	if test t = "$equal_tree_marker" ; then
+		# first apply all the changes to the old branch
+		old_tree=$(tree_of_commit "$orig_head")
+		new_tree=$(tree_of_commit HEAD)
+		if test "$old_tree" = "$new_tree" ; then
+			old_branch="$orig_head"
+		else
+			# TODO: better commit message
+			old_branch=$(echo "rebase $head_name onto $onto" | git-commit-tree $new_tree -p "$orig_head" -p "$onto" )
+		fi
+		# then say the old branch can be upgraded to the new one:
+		git equal-tree-marker "$old_branch"
+	fi
 	case "$head_name" in
 	refs/*)
 		message="rebase finished: $head_name onto $onto"
@@ -220,6 +240,7 @@ do
 			end=$(cat "$dotest/end")
 			msgnum=$(cat "$dotest/msgnum")
 			onto=$(cat "$dotest/onto")
+			equal_tree_marker=$(cat "$dotest/eqt")
 			GIT_QUIET=$(cat "$dotest/quiet")
 			continue_merge
 			while test "$msgnum" -le "$end"
@@ -234,6 +255,7 @@ do
 		onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
 		orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
 		GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
+		equal_tree_marker=$(cat "$GIT_DIR"/rebase-apply/eqt)
 		git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
 		move_to_original_branch
 		exit
@@ -251,6 +273,7 @@ do
 			msgnum=$(cat "$dotest/msgnum")
 			msgnum=$(($msgnum + 1))
 			onto=$(cat "$dotest/onto")
+			equal_tree_marker=$(cat "$dotest/eqt")
 			GIT_QUIET=$(cat "$dotest/quiet")
 			while test "$msgnum" -le "$end"
 			do
@@ -264,6 +287,7 @@ do
 		onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
 		orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
 		GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
+		equal_tree_marker=$(cat "$GIT_DIR"/rebase-apply/eqt)
 		git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
 		move_to_original_branch
 		exit
@@ -340,6 +364,9 @@ do
 		git_am_opt="$git_am_opt $1"
 		force_rebase=t
 		;;
+	--eqt)
+		equal_tree_marker=t
+		;;
 	-C*)
 		git_am_opt="$git_am_opt $1"
 		;;
@@ -522,7 +549,8 @@ then
 		echo $head_name > "$GIT_DIR"/rebase-apply/head-name &&
 		echo $onto > "$GIT_DIR"/rebase-apply/onto &&
 		echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head &&
-		echo "$GIT_QUIET" > "$GIT_DIR"/rebase-apply/quiet
+		echo "$GIT_QUIET" > "$GIT_DIR"/rebase-apply/quiet &&
+		echo "$equal_tree_marker" > "$GIT_DIR"/rebase-apply/eqt
 	exit $ret
 fi
 
@@ -537,6 +565,7 @@ echo "$prev_head" > "$dotest/prev_head"
 echo "$orig_head" > "$dotest/orig-head"
 echo "$head_name" > "$dotest/head-name"
 echo "$GIT_QUIET" > "$dotest/quiet"
+echo "$equal_tree_marker" > "$dotest/eqt"
 
 msgnum=0
 for cmt in `git rev-list --reverse --first-equal-tree-only --no-merges "$revisions"`

^ permalink raw reply related

* [PATCH 7/7] add support for creating equal tree markers to rebase -i
From: Bernhard R. Link @ 2009-11-30 14:45 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

With the new --eqt option, git rebase -i adds an equal tree marker,
so that the old branch can be fast-forwarded to the new one.
If the trees are not equal, a fake merge of the new base and
the old branch is created first.

TODO:
- manpage update,
- should --eqt have a better (longer more descriptive) name?
- the commit message of the merge should have a better default
  and presented to the user for editing
---
 git-rebase--interactive.sh |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 3da9f3e..51cc5fa 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -20,6 +20,7 @@ v,verbose          display a diffstat of what changed upstream
 onto=              rebase onto given branch instead of upstream
 p,preserve-merges  try to recreate merges instead of ignoring them
 s,strategy=        use the given merge strategy
+eqt                create an equal tree marker to allow f-f from old tree
 m,merge            always used (no-op)
 i,interactive      always used (no-op)
  Actions:
@@ -46,6 +47,7 @@ ONTO=
 VERBOSE=
 OK_TO_SKIP_PRE_REBASE=
 REBASE_ROOT=
+EQUAL_TREE_MARKER=
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -325,6 +327,11 @@ peek_next_command () {
 	sed -n "1s/ .*$//p" < "$TODO"
 }
 
+# is there really no already existing function for this?
+tree_of_commit() {
+	git cat-file commit "$1" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'
+}
+
 do_next () {
 	rm -f "$DOTEST"/message "$DOTEST"/author-script \
 		"$DOTEST"/amend || exit
@@ -426,6 +433,25 @@ do_next () {
 	esac
 	test -s "$TODO" && return
 
+	if test t = "$(cat "$DOTEST/eqt")" ; then
+		HEADNAME=$(cat "$DOTEST"/head-name)
+		OLDHEAD=$(cat "$DOTEST"/head)
+		ONTO=$(cat "$DOTEST"/onto)
+		NEWHEAD=$(git rev-parse HEAD)
+		OLDTREE=$(tree_of_commit "$OLDHEAD")
+		NEWTREE=$(tree_of_commit HEAD)
+		if test "$NEWTREE" = "$OLDTREE" ; then
+			OLDBRANCH="$OLDHEAD"
+		else
+			echo "Creating commit with differences of '$OLDHEAD' now that is applied to '$ONTO' (tree $NEWTREE)"
+			OLDBRANCH="$( (grep '^# Rebase' "$TODO".full \
+				; grep -v '^#' "$TODO".full ) \
+				| git-commit-tree "$NEWTREE" \
+				-p "$OLDHEAD" -p "$ONTO")"
+		fi
+		git equal-tree-marker "$OLDBRANCH"
+	fi
+
 	comment_for_reflog finish &&
 	HEADNAME=$(cat "$DOTEST"/head-name) &&
 	OLDHEAD=$(cat "$DOTEST"/head) &&
@@ -605,6 +631,9 @@ first and then run 'git rebase --continue' again."
 		ONTO=$(git rev-parse --verify "$1") ||
 			die "Does not point to a valid commit: $1"
 		;;
+	--eqt)
+		EQUAL_TREE_MARKER=t
+		;;
 	--)
 		shift
 		test -z "$REBASE_ROOT" -a $# -ge 1 -a $# -le 2 ||
@@ -656,6 +685,7 @@ first and then run 'git rebase --continue' again."
 			: >"$DOTEST"/rebase-root ;;
 		esac
 		echo $ONTO > "$DOTEST"/onto
+		echo "$EQUAL_TREE_MARKER" > "$DOTEST"/eqt
 		test -z "$STRATEGY" || echo "$STRATEGY" > "$DOTEST"/strategy
 		test t = "$VERBOSE" && : > "$DOTEST"/verbose
 		if test t = "$PRESERVE_MERGES"
@@ -787,6 +817,8 @@ EOF
 
 		test -d "$REWRITTEN" || skip_unnecessary_picks
 
+		cp "$TODO" "$TODO".full
+
 		git update-ref ORIG_HEAD $HEAD
 		output git checkout $ONTO && do_rest
 		;;

^ permalink raw reply related

* Re: equal-tree-merges as way to make rebases fast-forward-able
From: Sverre Rabbelier @ 2009-11-30 15:10 UTC (permalink / raw)
  To: Bernhard R. Link; +Cc: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

Heya,

On Mon, Nov 30, 2009 at 15:43, Bernhard R. Link <brlink@debian.org> wrote:
> Those patches are a bit rough and mostly intended to show how it could work
> and to allow experimenting with it.

Given the experimental nature of your patches it would probably have
been appropriate to mark them "RFC" (request for comment). You can do
so by running: `git format-patch --subject-prefix="RFC PATCH"` instead
of "git format-patch".

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: equal-tree-merges as way to make rebases fast-forward-able
From: Paolo Bonzini @ 2009-11-30 15:31 UTC (permalink / raw)
  To: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

On 11/30/2009 03:43 PM, Bernhard R. Link wrote:
> The itch this idea is supposed to scratch is the problem that a rebase
> or a amended commit is no longer a fast-forward, so cannot be easily
> pulled.

How does this compare with topgit?

Paolo

^ permalink raw reply

* Re: equal-tree-merges as way to make rebases fast-forward-able
From: Michael J Gruber @ 2009-11-30 15:35 UTC (permalink / raw)
  To: Bernhard R. Link; +Cc: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

Bernhard R. Link venit, vidit, dixit 30.11.2009 15:43:
> The itch this idea is supposed to scratch is the problem that a rebase
> or a amended commit is no longer a fast-forward, so cannot be easily
> pulled.

Do you mean pushed?
For pull, the state of the branch on the receiving side play a role, of
course.

> While this is not a problem in most workflows, as one can either merge
> or keep everything private and rebase until published, it would be nice
> to have a way for cases in between, where both a clean presentable
> commit order is to be maintained and people (or yourself from different
> repositories) should be able to easily upgrade to newer versions without
> an error-prone not-fast-forward.
> 
> My idea to solve this is combining both histories, the rebased/revised
> history and the actualy history, marking with some "equal-tree-merge"
> the point where they have the same result.
> The following mails show some patches to implement this by means of
> a merge where all parents have the same tree and some special casing
> when encountering such a thing. This has the advantage that older git
> version will just see strange merges and may present both histories,
> but otherwise just work.

Without having the time to go through the detailed setup you described
below (sorry), I'm wondering how this differs from what Git calls a
trivial merge? Is it merely about asserting that you merge coinciding
(heads with) trees?

Michael

^ permalink raw reply

* Re: [PATCH 1/7] add new command git equal-tree-marker
From: Michael J Gruber @ 2009-11-30 15:36 UTC (permalink / raw)
  To: Bernhard R. Link; +Cc: git
In-Reply-To: <9e6833ef7188f41d6ea46ddcf92929af284b4adb.1259524136.git.brlink@debian.org>

Bernhard R. Link venit, vidit, dixit 30.11.2009 15:43:
> This adds a new commit denoting tha current branch has the same
> tree as another branch, thus allowing fast-forward from the named
> commits to this one.
> 
> TODO: manpage, rewrite as builtin once the semantics are accepted?
> ---
>  .gitignore               |    1 +
>  Makefile                 |    1 +
>  git-equal-tree-marker.sh |   50 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 52 insertions(+), 0 deletions(-)
>  create mode 100644 git-equal-tree-marker.sh
> 
> diff --git a/.gitignore b/.gitignore
> index ac02a58..248d146 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -39,6 +39,7 @@
>  /git-difftool
>  /git-difftool--helper
>  /git-describe
> +/git-equal-tree-marker
>  /git-fast-export
>  /git-fast-import
>  /git-fetch
> diff --git a/Makefile b/Makefile
> index 4dba10e..913d4c4 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -336,6 +336,7 @@ TEST_PROGRAMS =
>  SCRIPT_SH += git-am.sh
>  SCRIPT_SH += git-bisect.sh
>  SCRIPT_SH += git-difftool--helper.sh
> +SCRIPT_SH += git-equal-tree-marker.sh
>  SCRIPT_SH += git-filter-branch.sh
>  SCRIPT_SH += git-lost-found.sh
>  SCRIPT_SH += git-merge-octopus.sh
> diff --git a/git-equal-tree-marker.sh b/git-equal-tree-marker.sh
> new file mode 100644
> index 0000000..403cc56
> --- /dev/null
> +++ b/git-equal-tree-marker.sh
> @@ -0,0 +1,50 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2009 Bernhard R. Link
> +#
> +# Create a new commit making HEAD parent of the arguments,
> +# which must be commits with the same tree.
> +
> +set -e
> +
> +USAGE='<head>...'
> +LONG_USAGE='Make current HEAD parent of the given heads (which need to have the same tree).'
> +SUBDIRECTORY_OK=Yes
> +OPTIONS_SPEC=
> +. git-sh-setup
> +cd_to_toplevel
> +
> +# is there really no function for this?
> +tree_of_commit() {
> +	git cat-file commit "$1" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'
> +}

You mean there should be something really simple, such as:

git rev-parse "$1"^{tree}

Michael

^ permalink raw reply

* Re: git archive without path
From: Dmitry Potapov @ 2009-11-30 15:45 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: git
In-Reply-To: <4B13C2FE.3040707@drmicha.warpmail.net>

On Mon, Nov 30, 2009 at 4:05 PM, Michael J Gruber
<git@drmicha.warpmail.net> wrote:
>
> Depends on the definition of "all" :)

I don't think it caries any restriction clause in this case....

>
> In fact: Two mighty powers are fighting right now for the primacy in the
> Land of the Git, and both carry the name "consistency" on their flags.
> One is the "order of the consistency of generations", also named
> "backwards compatibility", and one is the "order of the consistency of
> commands", also named "user experience".
>
> Many commands have different defaults with respect to how they behave in
> a subdirectory (compare status to ls-files, e.g.), and the discussion
> about how to best change that are underway, most prominently in the case
> of git grep.

Well, "order of the consistency" is a noble cause, but I don't think the
situations are comparable. The man page for git-grep has never claimed
that git grep works on all files. Also, git grep works on the working tree
by default, so defaulting to the current working directory at least makes
some sense. I cannot say the same about git-archive, which only works
on the repository and if I specified some revision without any path then
I expect to have the whole archive not some part of it just because I
happened to be in some subdirectory.

So, in the case of git-grep, we speak about changing the behavior that
was well-known, often used, and documented as such. On contrast,
git-archive documented as including all files if path is not specified.

Dmitry

^ permalink raw reply

* Re: equal-tree-merges as way to make rebases fast-forward-able
From: Michael J Gruber @ 2009-11-30 15:59 UTC (permalink / raw)
  To: Bernhard R. Link; +Cc: git
In-Reply-To: <cover.1259524136.git.brlink@debian.org>

Bernhard R. Link venit, vidit, dixit 30.11.2009 15:43:
[...]

Ok, I couldn't resist looking at your examples. Actually, before
anything else: Thanking for describing *what* you want to achieve, not
only how.

> Example 1:
> 
> Let's assume you maintain such a regularily-rebased branch that you
> want to be able to publish (or pull from other repositories for example
> on your laptop):
> 
> o=m=o=o=master
>    \
>     a=b=c=d=e=feature
> 
> with this patch you can do "git rebase -eqt master" and get:
> 
>               a'=b'=c'=d'=e'=feature'=eqt
>              /                       /
> o=m=o=o=master--------              /
>    \                  \            /
>     a=b=c=d=e=feature--merge-------
> 

git checkout -b featureprime feature
git rebase master
git merge feature # should be trivial
git branch -M featureprime feature

> i.e: the new feature branch has both histories:
>   - "feature'" where everything is cleanly rebased and in a form where
>                format-patch is suitable to send it upstream
>   - "merge" which is both a descendant from feature (so one can see what
>     changed since that time and can just pull when one had had cloned feature)
> 
> Example 2:
> 
> Let's assume you have a feature branch like
> 
> o=master
>    \
>     a=b=c=d=e=f
> 
> Assume you just commited "f" which fixes a bug introduced by "b".
> Now you of course do not want to send it that way upstream (as it will
> make reviewing harder, may force people bisecting to skip some versions
> every time they hit this region and so on), so you want to
> bisect -i and squash "f" into "b".
> 
> o=master
>    \
>     a=b+f=c'=d'=e'
> 
> But if you had already cloned at state "d" to your laptop (or made a backup
> of that branch at some server, or published it for use of some collegues)
> it will not be a fast-forward, so you have to be very carefull to not
> accidentially lose a commit that is already there.
> 
> So with this patches you can do "git rebase -i --eqt" and squash f into b
> and get:
> 
> o=master
>    \
>     a=b=c=d=e=f---
>      \            \
>       b+f=c'=d'=e'=eqt
> 
> which means that you can just pull from your laptop and get the new head
> as fast-forward, but still have a proper history ready for submitting.

If that side branch is named "feature":
git checkout -b fixup feature
git rebase -i a # squash f into b; creates b+f c# d' e'
git merge feature # should be trivial
git branch -M fixup feature

You can also go crazy with rebase --onto here, or use cherry-pick
repeatedly.

Note that I always use a temporary branch for rewriting, before renaming
it to the proper branch name. I haven't checked, but I assume the
"first-parents" are the way you want them (you want log --first-parent
--no-merges to show the rewritten commits, right?); otherwise you would
have to do the merges the other way round.

Cheers,
Michael

^ 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