Git development
 help / color / mirror / Atom feed
* Re: [PATCH] Many new features for cg-diff and cg-log
From: Petr Baudis @ 2005-06-08 20:40 UTC (permalink / raw)
  To: Dan Holmsand; +Cc: git
In-Reply-To: <42A754D5.10705@gmail.com>

Dear diary, on Wed, Jun 08, 2005 at 10:28:05PM CEST, I got a letter
where Dan Holmsand <holmsand@gmail.com> told me that...
> Petr Baudis wrote:
> >FYI, I plan to release 0.11.2 this evening. I'll try to go through some
> >more queued patches before and update cg-log to fully use git-rev-list.
> 
> In that case, you might want to have a look at this patch. I've been 
> tinkering with cg-log and cg-diff for some time, and just about got 
> ready to send you a patch.
> 
> Sorry about the monster patch, but I wanted to get it to you quickly...

Well, it can always go to 0.11.3 or something.  I probably wouldn't take
it to the tree just before release anyway even if you sent it split up,
since due to the size of the changes, it's bound to have some hidden
bugs. ;-)

> [PATCH] Many new features for cg-diff and cg-log

Ok, this is really too big. Could you please split it up some? Also,
I've been hacking on cg-log too (and will make it use git-diff-tree -v
yet this evening), so you'll need to update it to apply to the latest
version.

I like what's inside (at least from the description), though! (Well,
mostly. But I'll comment on specific patches. No major objections.)

> - Selection of ranges by date or maximum number of commits to show.

Ad date, isn't that already supported now? The -r arguments can be a
date. Ad maximum number of commits, what'd be its use?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Handling merge conflicts a bit more gracefully..
From: Linus Torvalds @ 2005-06-08 20:55 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Junio C Hamano, Jeff Garzik


Ok, Jeff reported that whenever there is a merge conflict, he ends up 
really punting on it and doing it all with diffs, which clearly meant that 
I had to fix up my silly things for this. Which I think I've done now.

What happens now in the case of a merge conflict is:
 - the merge is obviously not committed
 - we do all the successful merges, and update the index file for them
 - for the files that conflict, we force the index to contain the old
   version of the file (ie we remove the merge from the index), and we
   write the (failed) output of the merge into the working directory, and
   we complain loudly:

	Auto-merging xyzzy.
	merge: warning: conflicts during merge
	ERROR: Merge conflict in xyzzy.
	fatal: merge program failed
	Automatic merge failed, fix up by hand

at which point a normal "git-diff-files -p xyzzy" will show the incomplete
merge results (as relative to the original BRANCH you started with), and
in fact you can also do "git-diff-cache -p MERGE_HEAD xyzzy" to see the
same thing (but relative to the branch you tried to merge).

You then fix up the merge failure by hand (exactly the way you'd do with 
CVS), and you do a "git-update-cache xyzzy" when you're happy with the end 
result. Then a simple "git commit" should do the right thing.

If you decide that the merge is too hard to undo, you'd do:

	git-read-tree -u -m HEAD
	rm .git/MERGE_HEAD

and use git-checkout-cache judiciously to remove any edits the merge did.

This is definitely not perfect, but it's a hell of a lot more usable than
it used to be, and not really worse than what CVS people are used to (and
usually a lot better, since git will obviously get the origin of a
three-way merge right, unlike CVS).

Comments? It would be good to have people test this and maybe even write a 
few automated tests that it all works as expected..

		Linus

^ permalink raw reply

* [PATCH] Tidy up some rev-list-related stuff
From: Petr Baudis @ 2005-06-08 20:59 UTC (permalink / raw)
  To: torvalds; +Cc: Jon Seymour, git

This patch tidies up the git-rev-list documentation and epoch.c, which
are in severe clash with the unwritten coding style now, and quite
unreadable.

The patch mostly wraps lines before or on the 80th column, removes
plenty of superfluous empty lines and changes comments from // to /* */.

Signed-off-by: Petr Baudis <pasky@ucw.cz>

---

Jon, since this is your stuff, could you ack the patch, please?
Thanks.

I'm sorry to send patches like this, but I think the files are really
ugly as of now, and not very readable. This should be a definite
improvement in this regard, I hope.

diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -17,30 +17,45 @@ Lists commit objects in reverse chronolo
 given commit, taking ancestry relationship into account.  This is
 useful to produce human-readable log output.
 
-If *--merge-order* is specified, the commit history is decomposed into a unique sequence of minimal, non-linear
-epochs and maximal, linear epochs. Non-linear epochs are then linearised by sorting them into merge order, which 
+If *--merge-order* is specified, the commit history is decomposed into a
+unique sequence of minimal, non-linear epochs and maximal, linear epochs.
+Non-linear epochs are then linearised by sorting them into merge order, which
 is described below.
 
-Maximal, linear epochs correspond to periods of sequential development. Minimal, non-linear epochs 
-correspond to periods of divergent development followed by a converging merge. The theory of epochs is described
-in more detail at link:http://blackcubes.dyndns.org/epoch/[http://blackcubes.dyndns.org/epoch/].
-
-The merge order for a non-linear epoch is defined as a linearisation for which the following invariants are true:
-
-    1. if a commit P is reachable from commit N, commit P sorts after commit N in the linearised list.
-    2. if Pi and Pj are any two parents of a merge M (with i < j), then any commit N, such that N is reachable from Pj
-       but not reachable from Pi, sorts before all commits reachable from Pi.
-   
-Invariant 1 states that later commits appear before earlier commits they are derived from.
-
-Invariant 2 states that commits unique to "later" parents in a merge, appear before all commits from "earlier" parents of
-a merge.
-
-If *--show-breaks* is specified, each item of the list is output with a 2-character prefix consisting of one of: 
- (|), (^), (=) followed by a space. 
-Commits marked with (=) represent the boundaries of minimal, non-linear epochs and correspond either to the start of a period of divergent development or to the end of such a period. 
-Commits marked with (|) are direct parents of commits immediately preceding the marked commit in the list.
-Commits marked with (^) are not parents of the immediately preceding commit. These "breaks" represent necessary discontinuities implied by trying to represent an arbtirary DAG in a linear form.
+Maximal, linear epochs correspond to periods of sequential development.
+Minimal, non-linear epochs correspond to periods of divergent development
+followed by a converging merge. The theory of epochs is described in more
+detail at
+link:http://blackcubes.dyndns.org/epoch/[http://blackcubes.dyndns.org/epoch/].
+
+The merge order for a non-linear epoch is defined as a linearisation for which
+the following invariants are true:
+
+    1. if a commit P is reachable from commit N, commit P sorts after commit N
+       in the linearised list.
+    2. if Pi and Pj are any two parents of a merge M (with i < j), then any
+       commit N, such that N is reachable from Pj but not reachable from Pi,
+       sorts before all commits reachable from Pi.
+
+Invariant 1 states that later commits appear before earlier commits they are
+derived from.
+
+Invariant 2 states that commits unique to "later" parents in a merge, appear
+before all commits from "earlier" parents of a merge.
+
+If *--show-breaks* is specified, each item of the list is output with a
+2-character prefix consisting of one of: (|), (^), (=) followed by a space.
+
+Commits marked with (=) represent the boundaries of minimal, non-linear epochs
+and correspond either to the start of a period of divergent development or to
+the end of such a period.
+
+Commits marked with (|) are direct parents of commits immediately preceding
+the marked commit in the list.
+
+Commits marked with (^) are not parents of the immediately preceding commit.
+These "breaks" represent necessary discontinuities implied by trying to
+represent an arbtirary DAG in a linear form.
 
 *--show-breaks* is only valid if *--merge-order* is also specified.
 
diff --git a/epoch.c b/epoch.c
--- a/epoch.c
+++ b/epoch.c
@@ -8,9 +8,10 @@
  *
  */
 #include <stdlib.h>
-#include <openssl/bn.h>		// provides arbitrary precision integers
-				// required to accurately represent fractional 
-				//mass
+
+/* Provides arbitrary precision integers required to accurately represent
+ * fractional mass: */
+#include <openssl/bn.h>
 
 #include "cache.h"
 #include "commit.h"
@@ -125,7 +126,6 @@ static struct fraction *add(struct fract
 static int compare(struct fraction *left, struct fraction *right)
 {
 	BIGNUM a, b;
-
 	int result;
 
 	BN_init(&a);
@@ -159,7 +159,8 @@ static struct mass_counter *new_mass_cou
 	copy(&mass_counter->seen, get_zero());
 
 	if (commit->object.util) {
-		die("multiple attempts to initialize mass counter for %s\n", sha1_to_hex(commit->object.sha1));
+		die("multiple attempts to initialize mass counter for %s",
+		    sha1_to_hex(commit->object.sha1));
 	}
 
 	commit->object.util = mass_counter;
@@ -174,64 +175,59 @@ static void free_mass_counter(struct mas
 	free(counter);
 }
 
-//
-// Finds the base commit of a list of commits.
-//
-// One property of the commit being searched for is that every commit reachable 
-// from the base commit is reachable from the commits in the starting list only 
-// via paths that include the base commit.
-//
-// This algorithm uses a conservation of mass approach to find the base commit.
-//
-// We start by injecting one unit of mass into the graph at each
-// of the commits in the starting list. Injecting mass into a commit
-// is achieved by adding to its pending mass counter and, if it is not already
-// enqueued, enqueuing the commit in a list of pending commits, in latest 
-// commit date first order.
-//
-// The algorithm then preceeds to visit each commit in the pending queue.
-// Upon each visit, the pending mass is added to the mass already seen for that 
-// commit and then divided into N equal portions, where N is the number of 
-// parents of the commit being visited. The divided portions are then injected 
-// into each of the parents.
-//
-// The algorithm continues until we discover a commit which has seen all the
-// mass originally injected or until we run out of things to do. 
-//
-// If we find a commit that has seen all the original mass, we have found
-// the common base of all the commits in the starting list. 
-//
-// The algorithm does _not_ depend on accurate timestamps for correct operation.
-// However, reasonably sane (e.g. non-random) timestamps are required in order 
-// to prevent an exponential performance characteristic. The occasional 
-// timestamp inaccuracy will not dramatically affect performance but may 
-// result in more nodes being processed than strictly necessary.
-//
-// This procedure sets *boundary to the address of the base commit. It returns 
-// non-zero if, and only if, there was a problem parsing one of the 
-// commits discovered during the traversal.
-//
+/*
+ * Finds the base commit of a list of commits.
+ *
+ * One property of the commit being searched for is that every commit reachable
+ * from the base commit is reachable from the commits in the starting list only
+ * via paths that include the base commit.
+ *
+ * This algorithm uses a conservation of mass approach to find the base commit.
+ *
+ * We start by injecting one unit of mass into the graph at each
+ * of the commits in the starting list. Injecting mass into a commit
+ * is achieved by adding to its pending mass counter and, if it is not already
+ * enqueued, enqueuing the commit in a list of pending commits, in latest
+ * commit date first order.
+ *
+ * The algorithm then preceeds to visit each commit in the pending queue.
+ * Upon each visit, the pending mass is added to the mass already seen for that
+ * commit and then divided into N equal portions, where N is the number of
+ * parents of the commit being visited. The divided portions are then injected
+ * into each of the parents.
+ *
+ * The algorithm continues until we discover a commit which has seen all the
+ * mass originally injected or until we run out of things to do.
+ *
+ * If we find a commit that has seen all the original mass, we have found
+ * the common base of all the commits in the starting list.
+ *
+ * The algorithm does _not_ depend on accurate timestamps for correct operation.
+ * However, reasonably sane (e.g. non-random) timestamps are required in order
+ * to prevent an exponential performance characteristic. The occasional
+ * timestamp inaccuracy will not dramatically affect performance but may
+ * result in more nodes being processed than strictly necessary.
+ *
+ * This procedure sets *boundary to the address of the base commit. It returns
+ * non-zero if, and only if, there was a problem parsing one of the
+ * commits discovered during the traversal.
+ */
 static int find_base_for_list(struct commit_list *list, struct commit **boundary)
 {
-
 	int ret = 0;
-
 	struct commit_list *cleaner = NULL;
 	struct commit_list *pending = NULL;
-
-	*boundary = NULL;
-
 	struct fraction injected;
-
 	init_fraction(&injected);
+	*boundary = NULL;
 
 	for (; list; list = list->next) {
-
 		struct commit *item = list->item;
 
 		if (item->object.util) {
-			die("%s:%d:%s: logic error: this should not have happened - commit %s\n",
-			    __FILE__, __LINE__, __FUNCTION__, sha1_to_hex(item->object.sha1));
+			die("%s:%d:%s: logic error: this should not have happened - commit %s",
+			    __FILE__, __LINE__, __FUNCTION__,
+			    sha1_to_hex(item->object.sha1));
 		}
 
 		new_mass_counter(list->item, get_one());
@@ -242,81 +238,62 @@ static int find_base_for_list(struct com
 	}
 
 	while (!*boundary && pending && !ret) {
-
 		struct commit *latest = pop_commit(&pending);
-
 		struct mass_counter *latest_node = (struct mass_counter *) latest->object.util;
+		int num_parents;
 
 		if ((ret = parse_commit(latest)))
 			continue;
-
 		add(&latest_node->seen, &latest_node->seen, &latest_node->pending);
 
-		int num_parents = count_parents(latest);
-
+		num_parents = count_parents(latest);
 		if (num_parents) {
-
 			struct fraction distribution;
 			struct commit_list *parents;
 
 			divide(init_fraction(&distribution), &latest_node->pending, num_parents);
 
 			for (parents = latest->parents; parents; parents = parents->next) {
-
 				struct commit *parent = parents->item;
 				struct mass_counter *parent_node = (struct mass_counter *) parent->object.util;
 
 				if (!parent_node) {
-
 					parent_node = new_mass_counter(parent, &distribution);
-
 					insert_by_date(&pending, parent);
 					commit_list_insert(parent, &cleaner);
-
 				} else {
-
-					if (!compare(&parent_node->pending, get_zero())) {
+					if (!compare(&parent_node->pending, get_zero()))
 						insert_by_date(&pending, parent);
-					}
 					add(&parent_node->pending, &parent_node->pending, &distribution);
-
 				}
 			}
 
 			clear_fraction(&distribution);
-
 		}
 
-		if (!compare(&latest_node->seen, &injected)) {
+		if (!compare(&latest_node->seen, &injected))
 			*boundary = latest;
-		}
-
 		copy(&latest_node->pending, get_zero());
-
 	}
 
 	while (cleaner) {
-
 		struct commit *next = pop_commit(&cleaner);
 		free_mass_counter((struct mass_counter *) next->object.util);
 		next->object.util = NULL;
-
 	}
 
 	if (pending)
 		free_commit_list(pending);
 
 	clear_fraction(&injected);
-
 	return ret;
-
 }
 
 
-//
-// Finds the base of an minimal, non-linear epoch, headed at head, by
-// applying the find_base_for_list to a list consisting of the parents
-//
+/*
+ * Finds the base of an minimal, non-linear epoch, headed at head, by
+ * applying the find_base_for_list to a list consisting of the parents
+ */
 static int find_base(struct commit *head, struct commit **boundary)
 {
 	int ret = 0;
@@ -332,14 +309,14 @@ static int find_base(struct commit *head
 	return ret;
 }
 
-//
-// This procedure traverses to the boundary of the first epoch in the epoch
-// sequence of the epoch headed at head_of_epoch. This is either the end of
-// the maximal linear epoch or the base of a minimal non-linear epoch.
-//
-// The queue of pending nodes is sorted in reverse date order and each node
-// is currently in the queue at most once.
-//
+/*
+ * This procedure traverses to the boundary of the first epoch in the epoch
+ * sequence of the epoch headed at head_of_epoch. This is either the end of
+ * the maximal linear epoch or the base of a minimal non-linear epoch.
+ *
+ * The queue of pending nodes is sorted in reverse date order and each node
+ * is currently in the queue at most once.
+ */
 static int find_next_epoch_boundary(struct commit *head_of_epoch, struct commit **boundary)
 {
 	int ret;
@@ -350,10 +327,10 @@ static int find_next_epoch_boundary(stru
 		return ret;
 
 	if (HAS_EXACTLY_ONE_PARENT(item)) {
-
-		// we are at the start of a maximimal linear epoch .. traverse to the end
-
-		// traverse to the end of a maximal linear epoch
+		/*
+		 * We are at the start of a maximimal linear epoch.
+		 * Traverse to the end.
+		 */
 		while (HAS_EXACTLY_ONE_PARENT(item) && !ret) {
 			item = item->parents->item;
 			ret = parse_commit(item);
@@ -361,35 +338,35 @@ static int find_next_epoch_boundary(stru
 		*boundary = item;
 
 	} else {
-
-		// otherwise, we are at the start of a minimal, non-linear
-		// epoch - find the common base of all parents.
-
+		/*
+		 * Otherwise, we are at the start of a minimal, non-linear
+		 * epoch - find the common base of all parents.
+		 */
 		ret = find_base(item, boundary);
-
 	}
 
 	return ret;
 }
 
-//
-// Returns non-zero if parent is known to be a parent of child.
-//
+/*
+ * Returns non-zero if parent is known to be a parent of child.
+ */
 static int is_parent_of(struct commit *parent, struct commit *child)
 {
 	struct commit_list *parents;
 	for (parents = child->parents; parents; parents = parents->next) {
-		if (!memcmp(parent->object.sha1, parents->item->object.sha1, sizeof(parents->item->object.sha1)))
+		if (!memcmp(parent->object.sha1, parents->item->object.sha1,
+		            sizeof(parents->item->object.sha1)))
 			return 1;
 	}
 	return 0;
 }
 
-//
-// Pushes an item onto the merge order stack. If the top of the stack is
-// marked as being a possible "break", we check to see whether it actually
-// is a break.
-//
+/*
+ * Pushes an item onto the merge order stack. If the top of the stack is
+ * marked as being a possible "break", we check to see whether it actually
+ * is a break.
+ */
 static void push_onto_merge_order_stack(struct commit_list **stack, struct commit *item)
 {
 	struct commit_list *top = *stack;
@@ -401,54 +378,53 @@ static void push_onto_merge_order_stack(
 	commit_list_insert(item, stack);
 }
 
-//
-// Marks all interesting, visited commits reachable from this commit
-// as uninteresting. We stop recursing when we reach the epoch boundary,
-// an unvisited node or a node that has already been marking uninteresting.
-// This doesn't actually mark all ancestors between the start node and the
-// epoch boundary uninteresting, but does ensure that they will 
-// eventually be marked uninteresting when the main sort_first_epoch 
-// traversal eventually reaches them. 
-//
+/*
+ * Marks all interesting, visited commits reachable from this commit
+ * as uninteresting. We stop recursing when we reach the epoch boundary,
+ * an unvisited node or a node that has already been marking uninteresting.
+ *
+ * This doesn't actually mark all ancestors between the start node and the
+ * epoch boundary uninteresting, but does ensure that they will eventually
+ * be marked uninteresting when the main sort_first_epoch() traversal
+ * eventually reaches them.
+ */
 static void mark_ancestors_uninteresting(struct commit *commit)
 {
 	unsigned int flags = commit->object.flags;
 	int visited = flags & VISITED;
 	int boundary = flags & BOUNDARY;
 	int uninteresting = flags & UNINTERESTING;
+	struct commit_list *next;
 
 	commit->object.flags |= UNINTERESTING;
-	if (uninteresting || boundary || !visited) {
-		return;
 
-		// we only need to recurse if
-		//      we are not on the boundary, and,
-		//      we have not already been marked uninteresting, and,
-		//      we have already been visited.
-
-		//
-		// the main sort_first_epoch traverse will 
-		// mark unreachable all uninteresting, unvisited parents 
-		// as they are visited so there is no need to duplicate
-		// that traversal here.
-		//
-		// similarly, if we are already marked uninteresting
-		// then either all ancestors have already been marked
-		// uninteresting or will be once the sort_first_epoch
-		// traverse reaches them.
-		//
-	}
+	/*
+	 * We only need to recurse if
+	 *      we are not on the boundary and
+	 *      we have not already been marked uninteresting and
+	 *      we have already been visited.
+	 *
+	 * The main sort_first_epoch traverse will mark unreachable
+	 * all uninteresting, unvisited parents as they are visited
+	 * so there is no need to duplicate that traversal here.
+	 *
+	 * Similarly, if we are already marked uninteresting
+	 * then either all ancestors have already been marked
+	 * uninteresting or will be once the sort_first_epoch
+	 * traverse reaches them.
+	 */
 
-	struct commit_list *next;
+	if (uninteresting || boundary || !visited)
+		return;
 
 	for (next = commit->parents; next; next = next->next)
 		mark_ancestors_uninteresting(next->item);
 }
 
-//
-// Sorts the nodes of the first epoch of the epoch sequence of the epoch headed at head
-// into merge order.
-//
+/*
+ * Sorts the nodes of the first epoch of the epoch sequence of the epoch headed at head
+ * into merge order.
+ */
 static void sort_first_epoch(struct commit *head, struct commit_list **stack)
 {
 	struct commit_list *parents;
@@ -456,63 +432,59 @@ static void sort_first_epoch(struct comm
 
 	head->object.flags |= VISITED;
 
-	//
-	// parse_commit builds the parent list in reverse order with respect to the order of
-	// the git-commit-tree arguments.
-	//
-	// so we need to reverse this list to output the oldest (or most "local") commits last.
-	//
-
+	/*
+	 * parse_commit() builds the parent list in reverse order with respect
+	 * to the order of the git-commit-tree arguments. So we need to reverse
+	 * this list to output the oldest (or most "local") commits last.
+	 */
 	for (parents = head->parents; parents; parents = parents->next)
 		commit_list_insert(parents->item, &reversed_parents);
 
-	//
-	// todo: by sorting the parents in a different order, we can alter the 
-	// merge order to show contemporaneous changes in parallel branches
-	// occurring after "local" changes. This is useful for a developer
-	// when a developer wants to see all changes that were incorporated
-	// into the same merge as her own changes occur after her own
-	// changes.
-	//
+	/*
+	 * TODO: By sorting the parents in a different order, we can alter the
+	 * merge order to show contemporaneous changes in parallel branches
+	 * occurring after "local" changes. This is useful for a developer
+	 * when a developer wants to see all changes that were incorporated
+	 * into the same merge as her own changes occur after her own
+	 * changes.
+	 */
 
 	while (reversed_parents) {
-
 		struct commit *parent = pop_commit(&reversed_parents);
 
 		if (head->object.flags & UNINTERESTING) {
-			// propagates the uninteresting bit to
-			// all parents. if we have already visited
-			// this parent, then the uninteresting bit
-			// will be propagated to each reachable 
-			// commit that is still not marked uninteresting
-			// and won't otherwise be reached.
+			/*
+			 * Propagates the uninteresting bit to all parents.
+			 * if we have already visited this parent, then
+			 * the uninteresting bit will be propagated to each
+			 * reachable commit that is still not marked
+			 * uninteresting and won't otherwise be reached.
+			 */
 			mark_ancestors_uninteresting(parent);
 		}
 
 		if (!(parent->object.flags & VISITED)) {
 			if (parent->object.flags & BOUNDARY) {
-
 				if (*stack) {
-					die("something else is on the stack - %s\n", sha1_to_hex((*stack)->item->object.sha1));
+					die("something else is on the stack - %s",
+					    sha1_to_hex((*stack)->item->object.sha1));
 				}
-
 				push_onto_merge_order_stack(stack, parent);
 				parent->object.flags |= VISITED;
 
 			} else {
-
 				sort_first_epoch(parent, stack);
-
 				if (reversed_parents) {
-					//
-					// this indicates a possible discontinuity
-					// it may not be be actual discontinuity if
-					// the head of parent N happens to be the tail
-					// of parent N+1
-					//
-					// the next push onto the stack will resolve the 
-					// question
-					//
+					/*
+					 * This indicates a possible
+					 * discontinuity it may not be be
+					 * actual discontinuity if the head
+					 * of parent N happens to be the tail
+					 * of parent N+1.
+					 *
+					 * The next push onto the stack will
+					 * resolve the question.
+					 */
 					(*stack)->item->object.flags |= DISCONTINUITY;
 				}
 			}
@@ -522,27 +494,23 @@ static void sort_first_epoch(struct comm
 	push_onto_merge_order_stack(stack, head);
 }
 
-//
-// Emit the contents of the stack. 
-//
-// The stack is freed and replaced by NULL.
-//
-// Sets the return value to STOP if no further output should be generated.
-//
+/*
+ * Emit the contents of the stack.
+ *
+ * The stack is freed and replaced by NULL.
+ *
+ * Sets the return value to STOP if no further output should be generated.
+ */
 static int emit_stack(struct commit_list **stack, emitter_func emitter)
 {
 	unsigned int seen = 0;
 	int action = CONTINUE;
 
 	while (*stack && (action != STOP)) {
-
 		struct commit *next = pop_commit(stack);
-
 		seen |= next->object.flags;
-
-		if (*stack) {
+		if (*stack)
 			action = (*emitter) (next);
-		}
 	}
 
 	if (*stack) {
@@ -553,13 +521,13 @@ static int emit_stack(struct commit_list
 	return (action == STOP || (seen & UNINTERESTING)) ? STOP : CONTINUE;
 }
 
-//
-// Sorts an arbitrary epoch into merge order by sorting each epoch
-// of its epoch sequence into order.
-//
-// Note: this algorithm currently leaves traces of its execution in the
-// object flags of nodes it discovers. This should probably be fixed.
-//
+/*
+ * Sorts an arbitrary epoch into merge order by sorting each epoch
+ * of its epoch sequence into order.
+ *
+ * Note: this algorithm currently leaves traces of its execution in the
+ * object flags of nodes it discovers. This should probably be fixed.
+ */
 static int sort_in_merge_order(struct commit *head_of_epoch, emitter_func emitter)
 {
 	struct commit *next = head_of_epoch;
@@ -569,29 +537,24 @@ static int sort_in_merge_order(struct co
 	ret = parse_commit(head_of_epoch);
 
 	while (next && next->parents && !ret && (action != STOP)) {
-
 		struct commit *base = NULL;
 
-		if ((ret = find_next_epoch_boundary(next, &base)))
+		ret = find_next_epoch_boundary(next, &base);
+		if (ret)
 			return ret;
-
 		next->object.flags |= BOUNDARY;
-		if (base) {
+		if (base)
 			base->object.flags |= BOUNDARY;
-		}
 
 		if (HAS_EXACTLY_ONE_PARENT(next)) {
-
 			while (HAS_EXACTLY_ONE_PARENT(next)
 			       && (action != STOP)
 			       && !ret) {
-
 				if (next->object.flags & UNINTERESTING) {
 					action = STOP;
 				} else {
 					action = (*emitter) (next);
 				}
-
 				if (action != STOP) {
 					next = next->parents->item;
 					ret = parse_commit(next);
@@ -599,14 +562,11 @@ static int sort_in_merge_order(struct co
 			}
 
 		} else {
-
 			struct commit_list *stack = NULL;
 			sort_first_epoch(next, &stack);
 			action = emit_stack(&stack, emitter);
 			next = base;
-
 		}
-
 	}
 
 	if (next && (action != STOP) && !ret) {
@@ -616,29 +576,27 @@ static int sort_in_merge_order(struct co
 	return ret;
 }
 
-//
-// Sorts the nodes reachable from a starting list in merge order, we 
-// first find the base for the starting list and then sort all nodes in this 
-// subgraph using the sort_first_epoch algorithm. Once we have reached the base
-// we can continue sorting using sort_in_merge_order.
-//
+/*
+ * Sorts the nodes reachable from a starting list in merge order, we
+ * first find the base for the starting list and then sort all nodes
+ * in this subgraph using the sort_first_epoch algorithm. Once we have
+ * reached the base we can continue sorting using sort_in_merge_order.
+ */
 int sort_list_in_merge_order(struct commit_list *list, emitter_func emitter)
 {
 	struct commit_list *stack = NULL;
 	struct commit *base;
-
 	int ret = 0;
 	int action = CONTINUE;
-
 	struct commit_list *reversed = NULL;
 
 	for (; list; list = list->next) {
-
 		struct commit *next = list->item;
 
 		if (!(next->object.flags & UNINTERESTING)) {
 			if (next->object.flags & DUPCHECK) {
-				fprintf(stderr, "%s: duplicate commit %s ignored\n", __FUNCTION__, sha1_to_hex(next->object.sha1));
+				fprintf(stderr, "%s: duplicate commit %s ignored\n",
+					__FUNCTION__, sha1_to_hex(next->object.sha1));
 			} else {
 				next->object.flags |= DUPCHECK;
 				commit_list_insert(list->item, &reversed);
@@ -647,36 +605,35 @@ int sort_list_in_merge_order(struct comm
 	}
 
 	if (!reversed->next) {
-
-		// if there is only one element in the list, we can sort it using 
-		// sort_in_merge_order.
-
+		/*
+		 * If there is only one element in the list, we can sort it
+		 * using sort_in_merge_order.
+		 */
 		base = reversed->item;
-
 	} else {
-
-		// otherwise, we search for the base of the list
-
-		if ((ret = find_base_for_list(reversed, &base)))
+		/*
+		 * Otherwise, we search for the base of the list.
+		 */
+		ret = find_base_for_list(reversed, &base);
+		if (ret)
 			return ret;
-
-		if (base) {
+		if (base)
 			base->object.flags |= BOUNDARY;
-		}
 
 		while (reversed) {
 			sort_first_epoch(pop_commit(&reversed), &stack);
 			if (reversed) {
-				//
-				// if we have more commits to push, then the
-				// first push for the next parent may (or may not)
-				// represent a discontinuity with respect to the
-				// parent currently on the top of the stack.
-				//
-				// mark it for checking here, and check it
-				// with the next push...see sort_first_epoch for
-				// more details.
-				//
+				/*
+				 * If we have more commits to push, then the
+				 * first push for the next parent may (or may
+				 * not) represent a discontinuity with respect
+				 * to the parent currently on the top of
+				 * the stack.
+				 *
+				 * Mark it for checking here, and check it
+				 * with the next push. See sort_first_epoch()
+				 * for more details.
+				 */
 				stack->item->object.flags |= DISCONTINUITY;
 			}
 		}
diff --git a/rev-list.c b/rev-list.c
--- a/rev-list.c
+++ b/rev-list.c
@@ -214,17 +214,13 @@ int main(int argc, char **argv)
 		usage(rev_list_usage);
 
 	if (!merge_order) {		
-	
-	        if (limited) 
+	        if (limited)
 			list = limit_list(list);
 		show_commit_list(list);
-			
 	} else {
-		
 		if (sort_list_in_merge_order(list, &process_commit)) {
 			  die("merge order sort failed\n");
 		}
-					
 	}
 
 	return 0;

^ permalink raw reply

* Re: [PATCH] Many new features for cg-diff and cg-log
From: Petr Baudis @ 2005-06-08 21:03 UTC (permalink / raw)
  To: Dan Holmsand; +Cc: git
In-Reply-To: <20050608204012.GN982@pasky.ji.cz>

Dear diary, on Wed, Jun 08, 2005 at 10:40:13PM CEST, I got a letter
where Petr Baudis <pasky@ucw.cz> told me that...
> will make [cg-log] use git-diff-tree -v yet this evening

Ok, it turns out I won't. Feel free to hack on that. :-)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
<Espy> be careful, some twit might quote you out of context..

^ permalink raw reply

* Re: [PATCH] Many new features for cg-diff and cg-log
From: Dan Holmsand @ 2005-06-08 21:03 UTC (permalink / raw)
  To: git; +Cc: Petr Baudis
In-Reply-To: <20050608204012.GN982@pasky.ji.cz>

Petr Baudis wrote:
> Dear diary, on Wed, Jun 08, 2005 at 10:28:05PM CEST, I got a letter
> where Dan Holmsand <holmsand@gmail.com> told me that...
>>Sorry about the monster patch, but I wanted to get it to you quickly...
> 
> 
> Well, it can always go to 0.11.3 or something.  I probably wouldn't take
> it to the tree just before release anyway even if you sent it split up,
> since due to the size of the changes, it's bound to have some hidden
> bugs. ;-)

Nah... Seriously, that's a wise decision. I just saw that you we're 
working on cg-log, and wanted to save you some potential doublework by 
sending what I've got in a hurry.

I have, however, been using this myself for quite some time, so it's 
reasonably well tested.

>>[PATCH] Many new features for cg-diff and cg-log
> 
> 
> Ok, this is really too big. Could you please split it up some? Also,
> I've been hacking on cg-log too (and will make it use git-diff-tree -v
> yet this evening), so you'll need to update it to apply to the latest
> version.

Sure. I'll try to split it up, somewhat (but the changes *are* pretty 
inter-related...).
> 
> I like what's inside (at least from the description), though! (Well,
> mostly. But I'll comment on specific patches. No major objections.)
> 
> 
>>- Selection of ranges by date or maximum number of commits to show.
> 
> 
> Ad date, isn't that already supported now? The -r arguments can be a
> date. Ad maximum number of commits, what'd be its use?
> 

The new date thing doesn't work very well for cg-log: it's hardcoded to 
HEAD. That means that attempts to do, say, "cg-log -rorigin:-1day" will 
not at all do what you want. Not to mention "cg-log -m -r-1day". And I 
think it's a little clearer to separate the two: "cg-log -rorigin 
--max-age=-1day" (there's a short option too).

Max number of commits is perhaps not all that useful, unless you want to 
save cg-log output to file, for example. But it's easy to do :-)

Oh, and I forgot to mention the "pickaxe" support. "cg-log -S foobar" 
uses git-diff-tree -S to "search in diffs". Really very, very useful.

/dan


^ permalink raw reply

* [PATCH] Fix git-merge-one-file permissions auto-merging
From: Petr Baudis @ 2005-06-08 21:26 UTC (permalink / raw)
  To: torvalds; +Cc: git

In the automerge case, permissions were not restored properly after the
merge tool was invoked and overwrote the target file.

Signed-off-by: Petr Baudis <pasky@ucw.cz>

---
commit d0a0933d6ed6190a767f6baad6c93aa79b3901b2
tree 0a278964e7cd15b2f35b00551747c4908d65b244
parent 9d6694e94c2ff7fc24ecb4124234cef6c6037ad5
author Petr Baudis <pasky@ucw.cz> Wed, 08 Jun 2005 23:26:23 +0200
committer Petr Baudis <xpasky@machine.sinus.cz> Wed, 08 Jun 2005 23:26:23 +0200

 git-merge-one-file-script |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/git-merge-one-file-script b/git-merge-one-file-script
--- a/git-merge-one-file-script
+++ b/git-merge-one-file-script
@@ -63,10 +63,14 @@ case "${1:-.}${2:-.}${3:-.}" in
 	merge -p "$src1" "$orig" "$src2" > "$4"
 	ret=$?
 	rm -f -- "$orig" "$src1" "$src2"
+
 	if [ "$6" != "$7" ]; then
 		echo "ERROR: Permissions $5->$6->$7 don't match."
 		ret=1
 	fi
+	case "$6" in *7??) mode=+x;; *) mode=-x;; esac
+	chmod "$mode" "$4"
+
 	if [ $ret -ne 0 ]; then
 		# Reset the index to the first branch, making
 		# git-diff-file useful

|
-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
<Espy> be careful, some twit might quote you out of context..

^ permalink raw reply

* Re: Upstream merging and conflicts (was Re: Using cvs2git to track an external CVS project)
From: Martin Langhoff @ 2005-06-08 22:09 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0506080828240.2286@ppc970.osdl.org>

On 6/9/05, Linus Torvalds <torvalds@osdl.org> wrote:
> Yes, and right now that "manual" part is actualyl fairly high. I'll fix
> that thing up (today, I hope), making nontrivial merges much easier.

Wow -- I'll be tracking your tree closely then ;-)

> It's true that you can't skip patches, since a merge is always
> all-or-nothing, and the global history really requires that (in a very
> fundamental way). However, you _can_ merge from the HEAD, and then say
> "that patch is no longer relevant in this tree", and remove it. Then
> you'll never need to worry about that patch any more, because you've
> merged it and in your merged result, it no longer exists).

I had that strategy in my back-pocket already, but it doesn't sound right. 

> That said, I don't claim that this is what you always want to do. In fact,
> we have this exact issue in the kernel, and I think it's a great thing to
> use a combination of a patch-based system _and_ git. You use git for the
> "core", you use the patch-based system for the more fluid stuff. In the
> case of the kernel, the patch-based system that seems to be used the most
> is "quilt", but that's a detail. The big issue is that git is simply part
> of a bigger process:

Sounds like I'll be reading up on quilt then. I guess that's what I
was looking for...

> Yes. I think this is fundamental. "git" needs to converge. It's how git
> works. git also "crystallizes" the history and makes it unbreakable.
> Both of these things are _wonderful_ for what they mean, but both of these
> fundamental issues are _horrible_ for other reasons.

Fair enough -- and actually I'm not convinced it's a horrible thing.
Having worked with forever-diverging tools like Arch, I can appreciate
the value of crystallizing and identifying when you've converged --
and rebasing all steps forward on the fact that you've converged. This
is huge.

A patch-based workflow is needed in the periphery of HEAD -- but
patch-based tools fail to see when they've converged. What I am
salivating about is the idea of some basic patch smarts based on
git/cogito that I can use to track things in simplistic scenarios.
Right now as soon as I'm one patch "off" all of git support breaks
down and it's really hard to keep merging forward. Unless I merge &
reverse as discussed.

> So I don't think that you should necessarily think of git as "the" souce
> control management in the big picture. 

Yup. And quilt or other tools in the periphery. Something like the
git-aware darcs (which I haven't looked at yet).

> So I don't think any development effort that is big enough necessarily
> wants to use git as the _only_ way of doing development and merging stuff.
> The kernel certainly does not. Not now, and not in the long run.

Agreed. I'm happy to roll out some custom perl scripts around git (or
extend cogito a bit) if git can expose some stable holding points for
external tools to try and do some lightweight patch tracking.

> Whether the kernel model is applicable to anything else, I dunno.

I don't know either -- but I'm sure the toolset around git can support
a range of dev models. I don't think any other project has such a
large pool and strong convergence dynamics as the kernel. But git and
its tools and practices can be (I'm hoping) quite flexible to support
a range of dev models.

cheers,


martin

^ permalink raw reply

* [ANNOUNCE] Cogito-0.11.2
From: Petr Baudis @ 2005-06-08 23:07 UTC (permalink / raw)
  To: git

  Hello,

  I'm happy to announce Cogito-0.11.2, next version of my SCMish layer
over Linus' GIT tree history storage tool. You can get it as usual on

	kernel.org/pub/software/scm/cogito/

or by doing cg-update in your cogito.git repository.

  The changes include especially some bugfixes and portability and
performance enhancements, as well as all the sweet stuff from Linus.

  Note that I discovered a bug few minutes after releasing (as usual).
cg-log won't work correctly if ran with some files specified (the
"cg-log file" usage). I think it actually does not get used like this so
frequently, so I don't think it's worth another release by itself. But
expect new release as soon as some non-trivial amount of bugfixes piles
up (including core git bugfixes), quite soon hopefully.


  Here's git-rev-list --pretty HEAD ^cogito-0.11.1 | git-shortlog
(BTW, Dan, what about another cg-log option for git-shortlog output? ;-):


C. Cooke:
  Check whether the git repository is present before executing the command

Catalin Marinas:
  cg-commit: Fix the log file readin from stdin
  [PATCH Cogito] Add -f parameter also to cg-update

Chris Wedgwood:
  cogitio: sh != bash

Christian Meder:
  Miniscule correction of diff-format.txt

Dan Holmsand:
  Make cg-add use xargs -0

Daniel Barkalow:
  Document git-ssh-pull and git-ssh-push
  -w support for git-ssh-pull/push
  Generic support for pulling refs
  rsh.c environment variable
  Operations on refs
  ssh-protocol version, command types, response code

Eugene Surovegin:
  fix cg-commit new file handling

Jason McMullan:
  Anal retentive 'const unsigned char *sha1'
  Modify git-rev-list to linearise the commit history in merge order.

Jon Seymour:
  three --merge-order bug fixes

Jonas Fonseca:
  cg-commit: prefix pathspec argument with --
  git-diff-cache: handle pathspec beginning with a dash
  git-diff-cache: handle pathspec beginning with a dash
  cg-log: cleanup line wrapping by using bash internals
  Documentation improvements
  Misc cg-log documentation fixes
  Cleanup commit messages with git-stripspace
  [PATCH 10/10] Add -s option to show log summary
  [PATCH 9/10] Move file matching inside the loop.
  [PATCH 8/10] Move the username matching inside the loop
  [PATCH 7/10] Move log printing to separate function
  [PATCH 6/10] Remove the catch all rule
  [PATCH 5/10] Move printing of the commit info line inside the loop
  [PATCH 4/10] First parse all commit header entries then print them
  [PATCH 3/10] Separate handling of author and committer in commit headers
  [PATCH 2/10] Separate handling of tree and parent in commit headers
  [PATCH 1/10] Cleanup conversion to human readable date
  cg-Xnormid: support revision ids specified by date

Junio C Hamano:
  Tests: read-tree -m test updates.
  Documentation: describe diff tweaking (fix).
  Start cvs-migration documentation
  read-tree: update documentation for 3-way merge.
  read-tree: save more user hassles during fast-forward.
  index locking like everybody else
  3-way merge tests for new "git-read-tree -m"?
  rename git-rpush and git-rpull to git-ssh-push and git-ssh-pull
  Documentation: describe git extended diff headers.
  Documentation: describe diff tweaking.
  pull: gracefully recover from delta retrieval failure.
  diffcore-break.c: various fixes.
  diff.c: -B argument passing fix.
  diff.c: locate_size_cache() fix.
  diff: Update -B heuristics.
  diff: Clean up diff_scoreopt_parse().
  diff: Fix docs and add -O to diff-helper.
  Tweak count-delta interface
  Find size of SHA1 object without inflating everything.
  Handle deltified object correctly in git-*-pull family.

Linus Torvalds:
  Remove MERGE_HEAD after committing merge
  Make "git commit" work correctly in the presense of a manual merge
  cvs-migration: add more of a header to the "annotate" discussion
  Leave merge failures in the filesystem
  Fix SIGSEGV on unmerged files in git-diff-files -p
  Make default merge messages denser.
  git-apply: creatign empty files is nonfatal
  Talk about "git cvsimport" in the cvs migration docs
  git-read-tree: -u without -m is meaningless. Don't allow it.
  git-read-tree: make one-way merge also honor the "update" flag
  Add CVS import scripts and programs
  git-ssh-push/pull: usability improvements
  git-resolve-script: stop when the automated merge fails
  Make fetch/pull scripts terminate cleanly on errors
  git-resolve-script: don't wait for three seconds any more
  git-read-tree: some "final" cleanups
  git-read-tree: simplify merge loops enormously
  Add "__noreturn__" attribute to die() and usage()
  git-rev-list: make sure to link with ssl libraries
  Fix off-by-one in new three-way-merge updates
  Three-way merge: fix silly bug that made trivial merges not work
  Fix entry.c dependency and compile problem
  git-read-tree: fix up two-way merge
  More work on merging with git-read-tree..
  Make fiel checkout function available to the git library
  git-read-tree: fix up three-way merge tests
  git-read-tree: be a lot more careful about merging dirty trees
  diff 'rename' format change.
  git-apply: consider it an error to apply no changes
  git-apply: fix rename header parsing
  git-apply: actually apply patches and update the index
  git-apply: fix apply of a new file
  git-apply: find offset fragments, and really apply them
  git-apply: first cut at actually checking fragment data
  git-fsck-cache: complain if no default references found
  pretty_print_commit: add different formats
  git-shortlog: add name translations for 'sparse' repo
  Add git-shortlog perl script
  git-rev-list: allow arbitrary head selections, use git-rev-tree syntax
  Clarify git-diff-cache semantics in the tutorial.

Mark Allen:
  Modify cg-Xlib for non-GNU date.

Michal Rokos:
  [cogito] Sync objects only when needed
  [cogito] paged output for cg-diff
  Abstracted out $PAGER invocation to a pager() function

Petr Baudis:
  Fix cg-log called on specified files
  cogito-0.11.2
  Added trivial cg wrapper
  Use portable sed stuff in cg-log Signed-off-by highlighting
  showdate() now uses $(()) instead of $(expr)
  Fixed cg-log -u
  cg-merge now sometimes allows tree merge + local changes
  Add the t6001 testcase which got missed out at the last merge.
  Move commit line processing to process_commit_line
  Improved cg-Xmergefile
  Fix git-merge-one-file permissions auto-merging
  Fix cg-patch reverting file removal
  Reindent print_commit_log() body
  cg-log is now pure git-rev-list --pretty=raw frontend
  Fix cg-commit doing shell expansion on -m arguments
  Fix mismerged git-r* -> git-ssh-* rename in Makefile
  Move print_commit_log() in cg-log
  Fix an errorneous cg-clone example in the README
  Make git-update-cache --force-remove regular
  Portability sed fix in cg-commit
  Improve git-rev-list --header output
  Implement cg-rm -n for untracking files
  Fixed cg-Xnormid " " call
  cg-commit now updates cache separately for different change types
  Pass revisions to commit-id, parent-id, tree-id and cg-Xnormid quoted
  Do rm -f in make uninstall
  make dist will now produce tarball with sensible name

Rene Scharfe:
  git-tar-tree: do only basic tests in t/t5000-git-tar-tree.sh
  git-tar-tree: fix write_trailer
  git-tar-tree: add a test case
  git-tar-tree: small doc update
  git-tar-tree: cleanup write_trailer()

Sven Verdoolaege:
  git-cvs2git: create tags

Timo Hirvonen:
  Use ntohs instead of htons to convert ce_flags to host byte order


  Have fun,

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
<Espy> be careful, some twit might quote you out of context..

^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Junio C Hamano @ 2005-06-08 23:07 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506081336080.2286@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> What happens now in the case of a merge conflict is:
LT>  - the merge is obviously not committed
LT>  - we do all the successful merges, and update the index file for them
LT>  - for the files that conflict, we force the index to contain the old
LT>    version of the file (ie we remove the merge from the index), and we
LT>    write the (failed) output of the merge into the working directory, and
LT>    we complain loudly:

LT> Comments? It would be good to have people test this and maybe even write a 
LT> few automated tests that it all works as expected..

OK, I'll bite.  Other than some minor details, the work tree
seems to be updated with the result of the merge, either
successful one or failed one.

2a68a8659f7dc55fd285d235ae2d19e7a8116c30 \
(from f9e7750621ca5e067f58a679caff5ff2f9881c4c)
diff --git a/git-merge-one-file-script b/git-merge-one-file-script
--- a/git-merge-one-file-script
+++ b/git-merge-one-file-script
@@ -19,22 +19,25 @@ case "${1:-.}${2:-.}${3:-.}" in
 # Deleted in both.
 #
 "$1..")
-	echo "ERROR: $4 is removed in both branches."
-	echo "ERROR: This is a potential rename conflict."
-	exit 1;;
+	echo "WARNING: $4 is removed in both branches."
+	echo "WARNING: This is a potential rename conflict."
+	exec git-update-cache --remove -- "$4" ;;

Making sure that the path does not exist in the work tree with
test -f "$4" would be more sensible, before running --remove.

 #
 # Deleted in one and unchanged in the other.
 #
 "$1.." | "$1.$1" | "$1$1.")
 	echo "Removing $4"
-	exec git-update-cache --force-remove "$4" ;;
+	rm -f -- "$4"
+	exec git-update-cache --remove -- "$4" ;;

Make sure "$4" is not a directory, perhaps?  At least barf if
that 'rm -f -- "$4"' fails?

 #
 # Modified in both, but differently.
 #

@@ -55,19 +60,21 @@ case "${1:-.}${2:-.}${3:-.}" in
 	orig=`git-unpack-file $1`
 	src1=`git-unpack-file $2`
 	src2=`git-unpack-file $3`
-	merge "$src2" "$orig" "$src1"
+	merge -p "$src1" "$orig" "$src2" > "$4"
 	ret=$?
+	rm -f -- "$orig" "$src1" "$src2"
 	if [ "$6" != "$7" ]; then
 		echo "ERROR: Permissions $5->$6->$7 don't match."
+		ret=1
 	fi
 	if [ $ret -ne 0 ]; then
-		echo "ERROR: Leaving conflict merge in $src2."
+		# Reset the index to the first branch, making
+		# git-diff-file useful
+		git-update-cache --add --cacheinfo "$6" "$2" "$4"
+		echo "ERROR: Merge conflict in $4."
 		exit 1
 	fi
-	sha1=`git-write-blob "$src2"` || {
-		echo "ERROR: Leaving conflict merge in $src2."
-	}
-	exec git-update-cache --add --cacheinfo "$6" $sha1 "$4" ;;
+	exec git-update-cache --add -- "$4" ;;
 *)
 	echo "ERROR: Not handling case $4: $1 -> $2 -> $3" ;;
 esac

Again, make sure "$4" is not a directory before redirecting into
it from merge, so that you can tell merge failures from it?


^ permalink raw reply

* gitk (was Re: Linux v2.6.12-rc6)
From: Linus Torvalds @ 2005-06-08 23:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: Git Mailing List
In-Reply-To: <17062.21286.601768.751853@cargo.ozlabs.ibm.com>


Btw, Paul,
 one thing I end up missing in gitk is that looking at merges doesn't show 
any output, yet in many ways merges are actually the most interesting 
ones where you'd like to see where a file comes from..

Now, handling multi-way merges may be hard, but at least the normal 
two-way merges end up pretty straightforward, I think, and only have four 
cases for each file:
 - not touched by either side (ie it doesn't show up in either of 
   "git-diff-tree TREE PARENT1" or "git-diff-tree TREE PARENT2")
 - changed by PARENT1 only (ie it shows up in the git-diff-tree between 
   TREE and PARENT2)
 - changed by PARENT2 only
 - changed since both

and it would be cool if the "filename list" panel on the right side 
colorized the names by these things (only three cases - leave the "not 
touched" files off entirely, of course).

Also, it should actually possible to do a diff for these things with just
doing a "diff3" on the two parents and on the merge result (diff3 normally
expects the "original", but hey, the "original" might as well be the
result), and thus color a merge file by whether the lines came from one
side or the other or both (or neither, which would be a manual merge
fixup).

Maybe I'm crazy. But it _seems_ like a good idea that shouldn't be 
fundamentally hard.

		Linus

^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Linus Torvalds @ 2005-06-08 23:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vis0o30sc.fsf@assigned-by-dhcp.cox.net>



On Wed, 8 Jun 2005, Junio C Hamano wrote:
>  # Deleted in both.
> 
> Making sure that the path does not exist in the work tree with
> test -f "$4" would be more sensible, before running --remove.

Yeah, my (broken) thinking was that since it wasn't in both, it wasn't in 
the working directory either, but you're right, that's just crazy talk. 
There could be a stale file there.

Made it do a

	rm -f -- "$4" || exit 1

instead (and changed the other one to do the "|| exit 1" too, since you're 
also obviously right on the directory issue).

>  # Modified in both, but differently.
> +	merge -p "$src1" "$orig" "$src2" > "$4"
> 
> Again, make sure "$4" is not a directory before redirecting into
> it from merge, so that you can tell merge failures from it?

Hmm.. What's the cleanest way to check for redirection errors, but still
be able to distinguish those cleanly from "merge" itself returning an
error?

			Linus

^ permalink raw reply

* Re: [ANNOUNCE] Cogito-0.11.2
From: Dan Holmsand @ 2005-06-08 23:35 UTC (permalink / raw)
  To: git; +Cc: Petr Baudis
In-Reply-To: <20050608230725.GR982@pasky.ji.cz>

Petr Baudis wrote:
>   Here's git-rev-list --pretty HEAD ^cogito-0.11.1 | git-shortlog
> (BTW, Dan, what about another cg-log option for git-shortlog output? ;-):

Well, since I try to use the same output format as git-rev-list --pretty 
does (most of the time, it *is* just that...), I can actually already do

    cg-log -r:cogito-0.11.1 | git-shortlog

and get the same thing.

/dan


^ permalink raw reply

* [PATCH] git-merge-one-file-script cleanups from Cogito
From: Petr Baudis @ 2005-06-08 23:38 UTC (permalink / raw)
  To: torvalds; +Cc: git

Chain the resolving sequences (e.g. git-cat-file - chmod -
git-update-cache) through &&s so we stop right away in case one of the
command fails, and report the error code to the script caller.

Also add a copyright notice, some blank lines, ;; on a separate line,
and nicer error messages.

Signed-off-by: Petr Baudis <pasky@ucw.cz>

---
commit 99169278864b1adba5494d34f86c00d08ec0aff2
tree 5b9129ffe38c4286f65a6ddf97a0674bfc8942e3
parent c7773b6b3ab4f03a4e64084c0dc67045b283bc34
author Petr Baudis <pasky@ucw.cz> Thu, 09 Jun 2005 01:03:14 +0200
committer Petr Baudis <xpasky@machine.sinus.cz> Thu, 09 Jun 2005 01:03:14 +0200

 git-merge-one-file-script |   44 +++++++++++++++++++++++++++++---------------
 1 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/git-merge-one-file-script b/git-merge-one-file-script
--- a/git-merge-one-file-script
+++ b/git-merge-one-file-script
@@ -1,6 +1,8 @@
 #!/bin/sh
 #
-# This is the git merge script, called with
+# Copyright (c) Linus Torvalds, 2005
+#
+# This is the git per-file merge script, called with
 #
 #   $1 - original file SHA1 (or empty)
 #   $2 - file in branch1 SHA1 (or empty)
@@ -12,7 +14,7 @@
 #
 # Handle some trivial cases.. The _really_ trivial cases have
 # been handled already by git-read-tree, but that one doesn't
-# do any merges that migth change the tree layout.
+# do any merges that might change the tree layout.
 
 case "${1:-.}${2:-.}${3:-.}" in
 #
@@ -21,23 +23,29 @@ case "${1:-.}${2:-.}${3:-.}" in
 "$1..")
 	echo "WARNING: $4 is removed in both branches."
 	echo "WARNING: This is a potential rename conflict."
-	exec git-update-cache --remove -- "$4" ;;
+	exec git-update-cache --remove -- "$4"
+	;;
+
 #
 # Deleted in one and unchanged in the other.
 #
-"$1.." | "$1.$1" | "$1$1.")
+"$1.$1" | "$1$1.")
 	echo "Removing $4"
-	rm -f -- "$4"
-	exec git-update-cache --remove -- "$4" ;;
+	exec rm -f -- "$4" &&
+		git-update-cache --remove -- "$4"
+	;;
+
 #
 # Added in one.
 #
 ".$2." | "..$3" )
 	case "$6$7" in *7??) mode=+x;; *) mode=-x;; esac
 	echo "Adding $4 with perm $mode."
-	git-cat-file blob "$2$3" > "$4"
-	chmod $mode -- "$4"
-	exec git-update-cache --add -- "$4" ;;
+	exec git-cat-file blob "$2$3" >"$4" &&
+		chmod $mode -- "$4" &&
+		git-update-cache --add -- "$4"
+	;;
+
 #
 # Added in both (check for same permissions).
 #
@@ -49,9 +57,11 @@ case "${1:-.}${2:-.}${3:-.}" in
 	fi
 	case "$6" in *7??) mode=+x;; *) mode=-x;; esac
 	echo "Adding $4 with perm $mode"
-	git-cat-file blob "$2" > "$4"
-	chmod $mode -- "$4"
-	exec git-update-cache --add -- "$4" ;;
+	exec git-cat-file blob "$2" >"$4" &&
+		chmod $mode -- "$4" &&
+		git-update-cache --add -- "$4"
+	;;
+
 #
 # Modified in both, but differently.
 #
@@ -60,12 +70,13 @@ case "${1:-.}${2:-.}${3:-.}" in
 	orig=`git-unpack-file $1`
 	src1=`git-unpack-file $2`
 	src2=`git-unpack-file $3`
+
 	merge -p "$src1" "$orig" "$src2" > "$4"
 	ret=$?
 	rm -f -- "$orig" "$src1" "$src2"
 
 	if [ "$6" != "$7" ]; then
-		echo "ERROR: Permissions $5->$6->$7 don't match."
+		echo "ERROR: Permissions conflict: $5->$6,$7."
 		ret=1
 	fi
 	case "$6" in *7??) mode=+x;; *) mode=-x;; esac
@@ -78,8 +89,11 @@ case "${1:-.}${2:-.}${3:-.}" in
 		echo "ERROR: Merge conflict in $4."
 		exit 1
 	fi
-	exec git-update-cache --add -- "$4" ;;
+	exec git-update-cache --add -- "$4"
+	;;
+
 *)
-	echo "ERROR: Not handling case $4: $1 -> $2 -> $3" ;;
+	echo "ERROR: $4: Not handling case $1 -> $2 -> $3"
+	;;
 esac
 exit 1

|
-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
<Espy> be careful, some twit might quote you out of context..

^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Junio C Hamano @ 2005-06-09  0:03 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506081629370.2286@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

>> # Modified in both, but differently.
>> +	merge -p "$src1" "$orig" "$src2" > "$4"
>> 
>> Again, make sure "$4" is not a directory before redirecting into
>> it from merge, so that you can tell merge failures from it?

LT> Hmm.. What's the cleanest way to check for redirection errors, but still
LT> be able to distinguish those cleanly from "merge" itself returning an
LT> error?

I do not think you can, unless you are willing to parse shell
error messages, which I do not want you to be willing to ;-).

    : siamese; ls -dlF junk j.py
    ----------  1 junio junio  845 May  7  2004 j.py
    drwxrwxr-x  2 junio junio 4096 May  4 22:31 junk/
    : siamese; echo foo >j.py ; echo $?
    bash: j.py: Permission denied
    1
    : siamese; echo foo >junk ; echo $?
    bash: junk: Is a directory
    1

I think you have a bigger problem of leading paths, BTW.

Since we would want to have the merge result file at that path,
and not being able to create such is an error, how about doing
dumb and simple, like:

    d=`dirname "$4"` &&
    mkdir -p "$d" &&
    rm -f -- "$4" &&
    : >"$4" || {
        echo "barf"
        exit 1
    }
    merge -p "$src1" "$orig" "$src2" >"$4"
    ret=$?


^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Junio C Hamano @ 2005-06-09  0:11 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506081629370.2286@ppc970.osdl.org>

While I have your attention, I have been thinking about a
problem at lower level than what is being discussed.

Consider the following two command sequences:

     (1) git-read-tree -m $H $M	&& git-write-tree

     (2) I=`git-write-tree` &&
         git-read-tree -m $H $I $M &&
         git-merge-cache -o git-merge-one-file-script -a &&
         git-write-tree

I think they should be equivalent in that:

   - when (1) refuses to run, (2) should either cause
     git-read-tree to refuse, or at least should result in an
     unmerged cache and git-write-tree phase should fail;

   - when (1) succeeds, (2) should also succeed, and the
     resulting tree from both should be the same.



^ permalink raw reply

* Re: [RFC] rename/rename conflicts: do they matter?
From: Junio C Hamano @ 2005-06-09  0:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <7vll5k69y0.fsf@assigned-by-dhcp.cox.net>

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

JCH> I was reviewing git-merge-one-file-script, and started
JCH> thinking...

But somehow I got underwhelming responses.

I further think the "WARNING: " below is needlessly eating one
extra line of screen real estate without any additional value.

If one tree renamed a file (and creating the same or similar
file in another location) while the other tree kept the file
intact, then we would see "Removing $4" from the "deleted in one
and unchanged in the other" (and corresponding "Adding $4 with
perm $mode" for the rename destination).  If the user wants to
be careful about renames then all "Removing ..." need to be
examined _anyway_.  I would think it would be saner to collapse
these two case arms to catch "$1.." | "$1.$1" | "$1$1."  pattern
and just say "Removing $4".

    case "${1:-.}${2:-.}${3:-.}" in
    #
    # Deleted in both.
    #
    "$1..")
            echo "WARNING: $4 is removed in both branches."
            echo "WARNING: This is a potential rename conflict."
            rm -f -- "$4" &&
                    exec git-update-cache --remove -- "$4"
            ;;

    #
    # Deleted in one and unchanged in the other.
    #
    "$1.$1" | "$1$1.")
            echo "Removing $4"
            exec rm -f -- "$4" &&
                    git-update-cache --remove -- "$4"
            ;;



^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Linus Torvalds @ 2005-06-09  0:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmu01jmc.fsf@assigned-by-dhcp.cox.net>



On Wed, 8 Jun 2005, Junio C Hamano wrote:
> 
> I do not think you can, unless you are willing to parse shell
> error messages, which I do not want you to be willing to ;-).

Yeah, no. 

> I think you have a bigger problem of leading paths, BTW.

Gotcha. I committed a largely untested fix that hopefully does this all 
right.

I'm currently using your suggested thing (inside a function), but I think 
I'll instead make it do

	git-update-cache --add --cacheinfo ... &&
		git-checkout-cache -u -f "$4"

which seems even simpler.

		Linus

^ permalink raw reply

* Re: [PATCH] git-merge-one-file-script cleanups from Cogito
From: Linus Torvalds @ 2005-06-08 23:56 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20050608233820.GB9782@pasky.ji.cz>



On Thu, 9 Jun 2005, Petr Baudis wrote:
>
> Chain the resolving sequences (e.g. git-cat-file - chmod -
> git-update-cache) through &&s so we stop right away in case one of the
> command fails, and report the error code to the script caller.

Heh. This patch wouldn't apply, so I tried the new merge functionality on 
it. Seems to work. Goodie.

		Linus

^ permalink raw reply

* [PATCH] Add support reading default options from conf file
From: Jonas Fonseca @ 2005-06-09  1:00 UTC (permalink / raw)
  To: Dan Holmsand; +Cc: git, Petr Baudis

Reply-To: 
In-Reply-To: <42A754D5.10705@gmail.com>

Dan Holmsand <holmsand@gmail.com> wrote Wed, Jun 08, 2005:
> - Automatic color if the COGITO_AUTO_COLOR environment variable is set.

[ This has been discussed before. Default arguments. The 'new' cg
  wrapper makes this very easy. Not as smart as your env variable
  handling tho'. ]

The default options are read only for Cogito calls going through the new
cg wrapper which makes it trivial to 'overwrite' them by just calling
cg-COMMAMD.

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
---

 Documentation/make-cogito-asciidoc |   12 ++++++++++++
 cg                                 |    6 +++++-
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/Documentation/make-cogito-asciidoc b/Documentation/make-cogito-asciidoc
--- a/Documentation/make-cogito-asciidoc
+++ b/Documentation/make-cogito-asciidoc
@@ -140,6 +140,18 @@ FILE::
 	Indicates an already existing filename - always relative to the root
 	of the repository.
 
+FILES
+-----
+~/.cogito.conf::
+	This file is read when running the \`cg\` wrapper program and
+	contains information about default options. Each line consists
+	of a command name and a list of options. Empty lines and lines
+	starting with '#' are ignored. To always have \`cg log\` and
+	\`cg diff\` output colored put the following in ~/.cogito.conf:
+
+		log -c
+		diff -c
+
 COPYRIGHT
 ---------
 Copyright (C) Petr Baudis, 2005.
diff --git a/cg b/cg
--- a/cg
+++ b/cg
@@ -3,5 +3,9 @@
 cmd="$1"; shift
 [ x"$cmd" = x"--help" ] && cmd="help"
 
+if [ -e "$HOME/.cogito.conf" ]; then
+	defaults="$(grep "^$cmd" "$HOME/.cogito.conf" | sed "s/^$cmd //")"
+fi
+
 exe="cg-$cmd"
-exec $exe "$@"
+exec $exe "$defaults" "$@"

-- 
Jonas Fonseca

^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Junio C Hamano @ 2005-06-09  1:04 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506081738000.2286@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> I'll instead make it do

LT> 	git-update-cache --add --cacheinfo ... &&
LT> 		git-checkout-cache -u -f "$4"

LT> which seems even simpler.

I like that one much much better.  Consistently using
checkout-cache -f everywhere is much preferred.  It creates the
leading paths itself, and even nukes interfering files it finds
while creating leading directories, which the verify_path using
mkdir -p would not give you.


^ permalink raw reply

* Re: [PATCH] Tidy up some rev-list-related stuff
From: Jon Seymour @ 2005-06-09  1:06 UTC (permalink / raw)
  To: Petr Baudis; +Cc: torvalds, git
In-Reply-To: <20050608205943.GO982@pasky.ji.cz>

On 6/9/05, Petr Baudis <pasky@ucw.cz> wrote:
> This patch tidies up the git-rev-list documentation and epoch.c, which
> are in severe clash with the unwritten coding style now, and quite
> unreadable.
> 
> The patch mostly wraps lines before or on the 80th column, removes
> plenty of superfluous empty lines and changes comments from // to /* */.
> 
> Signed-off-by: Petr Baudis <pasky@ucw.cz>
> 
> ---
> 
> Jon, since this is your stuff, could you ack the patch, please?
> Thanks.
> 
> I'm sorry to send patches like this, but I think the files are really
> ugly as of now, and not very readable. This should be a definite
> improvement in this regard, I hope.
> 

Ack'd and tested.

Hey, no problem. I'll never learn unless someone corrects me. It does
make my next patch slightly tedious since I'll have to manually
reapply it, but hey, I am the new kid on the block, so kick dirt in my
face :-)

>From your patch I infer the following coding style rules:

Lines to wrap at column 80
One statement blocks should not include braces
Comment blocks should always be /* */ rather than //
Declarations should always be up the top of a block - never close to first use
No whitespace at top and bottom of blocks.
All indentation should use tabs and only tabs, set at tab stops of 8 apart.

Question: is // ever allowed?

Presumably, when in doubt should I use the kernel's CodingStyle
document as the default reference.

Speaking of which, I can't emacs to indent properly even when I use
this suggestion from that document:

    (defun linux-c-mode ()
      "C mode with adjusted defaults for use with the Linux kernel."
      (interactive)
      (c-mode)
      (c-set-style "K&R")
      (setq tab-width 8)
      (setq indent-tabs-mode t)
      (setq c-basic-offset 8))

    This will define the M-x linux-c-mode command.  When hacking on a
    module, if you put the string -*- linux-c -*- somewhere on the first
    two lines, this mode will be automatically invoked. Also, you may want
    to add

    (setq auto-mode-alist (cons '("/home/jon/.*/.*\\.[ch]$" . linux-c-mode)
                            auto-mode-alist))

It doesn't work when I execute linux-c-mode from the emacs command line either.

Any ideas at all what I am doing wrong? [ Apart from the ever so
constructive suggestion to use vi or vim - please! ]

jon.

^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Linus Torvalds @ 2005-06-09  1:08 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7voeag1j9y.fsf@assigned-by-dhcp.cox.net>



On Wed, 8 Jun 2005, Junio C Hamano wrote:
> 
> Consider the following two command sequences:
> 
>      (1) git-read-tree -m $H $M	&& git-write-tree
> 
>      (2) I=`git-write-tree` &&
>          git-read-tree -m $H $I $M &&
>          git-merge-cache -o git-merge-one-file-script -a &&
>          git-write-tree
> 
> I think they should be equivalent in that:
> 
>    - when (1) refuses to run, (2) should either cause
>      git-read-tree to refuse, or at least should result in an
>      unmerged cache and git-write-tree phase should fail;
> 
>    - when (1) succeeds, (2) should also succeed, and the
>      resulting tree from both should be the same.

I think that sounds reasonable. Is it not the case now?

		Linus

^ permalink raw reply

* Re: [PATCH] git-rev-list --merge-order resynched with Linus' head
From: Jon Seymour @ 2005-06-05 12:55 UTC (permalink / raw)
  To: jon@blackcubes.dyndns.org; +Cc: git, torvalds
In-Reply-To: <20050605072336.14283.qmail@blackcubes.dyndns.org>

Just discovered a few bugs in my revised patch...will repost when I
have fixed them.

jon.

^ permalink raw reply

* Re: Handling merge conflicts a bit more gracefully..
From: Junio C Hamano @ 2005-06-09  2:15 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0506081757170.2286@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> I think that sounds reasonable. Is it not the case now?

Well, except that $I may validly be an empty tree ;-), so not
quite.

In case it was not clear, where I am headed is this.  I would
like to rip out the two-tree "carry forward" implementation from
read-tree, and replace it with:

    read_cache() -- current goes to stage0
    read_tree(H) -- H goes to stage1
    read_tree(M) -- M goes to stage3
    for each path
        if it appears in stage0, copy it to stage2
        else if it appears in stage1, copy it to stage2
    threeway_merge() !!

And then the resulting possibly unmerged cache can be resolved
exactly the same way with merge-cache.

The trouble I feel with the current "carry forward" code is that
when it works it does sensible thing, but otherwise does not
help the end user at all.  With all the work going into making
merge-one-file-script nicer today, I think leveraging three-way
merge support for two-tree fast forward case would make a lot
more sense than keeping the all-or-nothing carry forward code I
recently added to it.

When/if that happens, then the current fast-forward code would
need to be changed from:

    read-tree -m $H $M && echo $M >.git/HEAD

to

    read-tree -m $H $M &&
    if unmerged paths in the resulting cache
    then
        merge-cache -o merge-one-file-script -a
    fi &&
    echo $M >.git/HEAD

and the user's local changes since H when fast forwarding to M
would be handled with the same workflow as the three-way case.

Hmm.


^ permalink raw reply

* Re: Upstream merging and conflicts (was Re: Using cvs2git to track an external CVS project)
From: Linus Torvalds @ 2005-06-09  2:34 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Git Mailing List
In-Reply-To: <46a038f905060815096382636a@mail.gmail.com>



On Thu, 9 Jun 2005, Martin Langhoff wrote:

> On 6/9/05, Linus Torvalds <torvalds@osdl.org> wrote:
> > Yes, and right now that "manual" part is actualyl fairly high. I'll fix
> > that thing up (today, I hope), making nontrivial merges much easier.
> 
> Wow -- I'll be tracking your tree closely then ;-)

Well, it's done, and it's now "much easier" in the sense that anything 
that doesn't have metadata changes should be picked up pretty trivially by 
the three-way merge thing.

But if you move things around, then you'd need to have a merge that is
aware of movement, ie something much more sophisticated than just 3way
merge.

> > It's true that you can't skip patches, since a merge is always
> > all-or-nothing, and the global history really requires that (in a very
> > fundamental way). However, you _can_ merge from the HEAD, and then say
> > "that patch is no longer relevant in this tree", and remove it. Then
> > you'll never need to worry about that patch any more, because you've
> > merged it and in your merged result, it no longer exists).
> 
> I had that strategy in my back-pocket already, but it doesn't sound right. 

With global history, you really don't end up having much choice. 

The alternative is to have per-file history, which sucks pretty bad
(you're screwed if you have a file that is touched by two things, so it
just moves the problem a bit, but more importantly you now have all the
CVS crud), or then you have to play games like arch or darcs which is all
about re-ordering patches (and then your history is totally malleable,
with all the problems that entails).

> > Yes. I think this is fundamental. "git" needs to converge. It's how git
> > works. git also "crystallizes" the history and makes it unbreakable.
> > Both of these things are _wonderful_ for what they mean, but both of these
> > fundamental issues are _horrible_ for other reasons.
> 
> Fair enough -- and actually I'm not convinced it's a horrible thing.

It's absolutely not horrible, but it limits how you work. _I_ think it 
limits you in good ways, but it's definitely a limitation.

> Having worked with forever-diverging tools like Arch, I can appreciate
> the value of crystallizing and identifying when you've converged --
> and rebasing all steps forward on the fact that you've converged. This
> is huge.

My gut feel is that it should be possible to have a hybrid system that
handles both the solid "crystalline" phase (aka git) and the "gas" phase
(aka free-lowing patches) and have them integrate with each other well. 
That's kind of the way the kernel works, with people using quilt as a way 
to capture the patches in between.

My read is that this analogy arch and darcs try to avoid the really solid
crystalline phase entirely and end up being amorphous. You can probably 
have that too, but on the other hand it's fairly easy to merge between two 
"crystallized" repositories and be totally unambigious about what the 
result is, but if there's a lot of the amorpous stuff going on, it's not 
clear any more.

> > Whether the kernel model is applicable to anything else, I dunno.
> 
> I don't know either -- but I'm sure the toolset around git can support
> a range of dev models. I don't think any other project has such a
> large pool and strong convergence dynamics as the kernel. But git and
> its tools and practices can be (I'm hoping) quite flexible to support
> a range of dev models.

Hey, I obviously think you're right. Using git gives good ways of
communicating the core infrastructure between two (or more) groups, while
then internally within the group they may use loser patch-tracking systems
that don't have the same kind of convergence requirements (but which you
don't need for a "small" set of patches anyway, where "small" can
obviously be hundreds of internal patches).

			Linus

^ 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