Git development
 help / color / mirror / Atom feed
* Re: [PATCH] git-cherry: make <upstream> parameter optional
From: Markus Heidelberg @ 2008-12-30 13:37 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0812301411480.30769@pacific.mpi-cbg.de>

Johannes Schindelin, 30.12.2008:
> Hi,
> 
> On Mon, 29 Dec 2008, Markus Heidelberg wrote:
> 
> > The upstream branch <upstream> now defaults to the first tracked
> > remote branch, which is set by the configuration variables
> > branch.<name>.remote and branch.<name>.merge of the current branch.
> > 
> > Without such a remote branch, the command "git cherry [-v]" fails with
> > usage output as before and an additional message.
> > 
> > Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>
> 
> This would be a massively visible user interface change.  At the moment, 
> it does this (which I like):
> 
> 	$ git cherry-pick
> 	usage: git cherry-pick [options] <commit-ish>
> 
> 	    -n, --no-commit       don't automatically commit
> 	    -e, --edit            edit the commit message
> 	    -x                    append commit name when cherry-picking
> 	    -r                    no-op (backward compatibility)
> 	    -s, --signoff         add Signed-off-by:
> 	    -m, --mainline <n>    parent number
> 
> Opposed,
> Dscho

The patch was about git-cherry, not git-cherry-pick.

Markus

^ permalink raw reply

* Re: [PATCH] git-cherry: make <upstream> parameter optional
From: Johannes Schindelin @ 2008-12-30 13:13 UTC (permalink / raw)
  To: Markus Heidelberg; +Cc: git
In-Reply-To: <200812291845.20500.markus.heidelberg@web.de>

Hi,

On Mon, 29 Dec 2008, Markus Heidelberg wrote:

> The upstream branch <upstream> now defaults to the first tracked
> remote branch, which is set by the configuration variables
> branch.<name>.remote and branch.<name>.merge of the current branch.
> 
> Without such a remote branch, the command "git cherry [-v]" fails with
> usage output as before and an additional message.
> 
> Signed-off-by: Markus Heidelberg <markus.heidelberg@web.de>

This would be a massively visible user interface change.  At the moment, 
it does this (which I like):

	$ git cherry-pick
	usage: git cherry-pick [options] <commit-ish>

	    -n, --no-commit       don't automatically commit
	    -e, --edit            edit the commit message
	    -x                    append commit name when cherry-picking
	    -r                    no-op (backward compatibility)
	    -s, --signoff         add Signed-off-by:
	    -m, --mainline <n>    parent number

Opposed,
Dscho

^ permalink raw reply

* [PATCH v2 3/3] rebase: update documentation for --root
From: Thomas Rast @ 2008-12-30 12:29 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <7b2902d36a4790670f20f786d4ea2e26052a6e71.1230639970.git.trast@student.ethz.ch>

Since the new option depends on --onto and omission of <upstream>, use
a separate invocation style, and omit most options to save space.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

Changed since v1: remark about the effect of --root --preserve-merges.

 Documentation/git-rebase.txt |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index c8ad86a..e3b4b83 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -8,10 +8,11 @@ git-rebase - Forward-port local commits to the updated upstream head
 SYNOPSIS
 --------
 [verse]
-'git rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
-	[-s <strategy> | --strategy=<strategy>] [--no-verify]
-	[-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
-	[--onto <newbase>] <upstream> [<branch>]
+'git rebase' [-i | --interactive] [options] [--onto <newbase>]
+	<upstream> [<branch>]
+'git rebase' [-i | --interactive] [options] --onto <newbase>
+	--root [<branch>]
+
 'git rebase' --continue | --skip | --abort
 
 DESCRIPTION
@@ -22,7 +23,8 @@ it remains on the current branch.
 
 All changes made by commits in the current branch but that are not
 in <upstream> are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`.
+of commits that would be shown by `git log <upstream>..HEAD` (or
+`git log HEAD`, if --root is specified).
 
 The current branch is reset to <upstream>, or <newbase> if the
 --onto option was supplied.  This has the exact same effect as
@@ -255,6 +257,13 @@ OPTIONS
 --preserve-merges::
 	Instead of ignoring merges, try to recreate them.
 
+--root::
+	Rebase all commits reachable from <branch>, instead of
+	limiting them with an <upstream>.  This allows you to rebase
+	the root commit(s) on a branch.  Must be used with --onto.
+	When used together with --preserve-merges, 'all' root commits
+	will be rewritten to have <newbase> as parent instead.
+
 include::merge-strategies.txt[]
 
 NOTES
-- 
1.6.1.20.g7f5c5.dirty

^ permalink raw reply related

* [PATCH v2 1/3] rebase: learn to rebase root commit
From: Thomas Rast @ 2008-12-30 12:29 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <200812301323.30550.trast@student.ethz.ch>

Teach git-rebase a new option --root, which instructs it to rebase the
entire history leading up to <branch>.

The main use-case is with git-svn: suppose you start hacking (perhaps
offline) on a new project, but later notice you want to commit this
work to SVN.  You will have to rebase the entire history, including
the root commit, on a (possibly empty) commit coming from git-svn, to
establish a history connection.  This previously had to be done by
cherry-picking the root commit manually.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

No changes since v1.

 git-rebase.sh          |   51 ++++++++++++++++++++++++++++++++--------------
 t/t3412-rebase-root.sh |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 16 deletions(-)
 create mode 100755 t/t3412-rebase-root.sh

diff --git a/git-rebase.sh b/git-rebase.sh
index ebd4df3..89de3c4 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano.
 #
 
-USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]'
+USAGE='[--interactive | -i] [-v] [--onto <newbase>] [<upstream>|--root] [<branch>]'
 LONG_USAGE='git-rebase replaces <branch> with a new branch of the
 same name.  When the --onto option is provided the new branch starts
 out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
@@ -47,6 +47,7 @@ dotest="$GIT_DIR"/rebase-merge
 prec=4
 verbose=
 git_am_opt=
+rebase_root=
 
 continue_merge () {
 	test -n "$prev_head" || die "prev_head must be defined"
@@ -297,6 +298,9 @@ do
 	-C*)
 		git_am_opt="$git_am_opt $1"
 		;;
+	--root)
+		rebase_root=t
+		;;
 	-*)
 		usage
 		;;
@@ -344,17 +348,23 @@ case "$diff" in
 	;;
 esac
 
+if test -z "$rebase_root"; then
 # The upstream head must be given.  Make sure it is valid.
-upstream_name="$1"
-upstream=`git rev-parse --verify "${upstream_name}^0"` ||
-    die "invalid upstream $upstream_name"
+	upstream_name="$1"
+	shift
+	upstream=`git rev-parse --verify "${upstream_name}^0"` ||
+	die "invalid upstream $upstream_name"
+fi
+
+test ! -z "$rebase_root" -a -z "$newbase" &&
+	die "--root must be used with --onto"
 
 # Make sure the branch to rebase onto is valid.
 onto_name=${newbase-"$upstream_name"}
 onto=$(git rev-parse --verify "${onto_name}^0") || exit
 
 # If a hook exists, give it a chance to interrupt
-run_pre_rebase_hook ${1+"$@"}
+run_pre_rebase_hook ${upstream_name+"$upstream_name"} "$@"
 
 # If the branch to rebase is given, that is the branch we will rebase
 # $branch_name -- branch being rebased, or HEAD (already detached)
@@ -362,16 +372,16 @@ run_pre_rebase_hook ${1+"$@"}
 # $head_name -- refs/heads/<that-branch> or "detached HEAD"
 switch_to=
 case "$#" in
-2)
+1)
 	# Is it "rebase other $branchname" or "rebase other $commit"?
-	branch_name="$2"
-	switch_to="$2"
+	branch_name="$1"
+	switch_to="$1"
 
-	if git show-ref --verify --quiet -- "refs/heads/$2" &&
-	   branch=$(git rev-parse -q --verify "refs/heads/$2")
+	if git show-ref --verify --quiet -- "refs/heads/$1" &&
+	   branch=$(git rev-parse -q --verify "refs/heads/$1")
 	then
-		head_name="refs/heads/$2"
-	elif branch=$(git rev-parse -q --verify "$2")
+		head_name="refs/heads/$1"
+	elif branch=$(git rev-parse -q --verify "$1")
 	then
 		head_name="detached HEAD"
 	else
@@ -393,7 +403,8 @@ case "$#" in
 esac
 orig_head=$branch
 
-# Now we are rebasing commits $upstream..$branch on top of $onto
+# Now we are rebasing commits $upstream..$branch (or simply $branch
+# with --root) on top of $onto
 
 # Check if we are already based on $onto with linear history,
 # but this should be done only when upstream and onto are the same.
@@ -429,10 +440,18 @@ then
 	exit 0
 fi
 
+if test ! -z "$rebase_root"; then
+	revisions="$orig_head"
+	fp_flag="--root"
+else
+	revisions="$upstream..$orig_head"
+	fp_flag="--ignore-if-in-upstream"
+fi
+
 if test -z "$do_merge"
 then
-	git format-patch -k --stdout --full-index --ignore-if-in-upstream \
-		"$upstream..$orig_head" |
+	git format-patch -k --stdout --full-index "$fp_flag" \
+		"$revisions" |
 	git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
 	move_to_original_branch
 	ret=$?
@@ -455,7 +474,7 @@ echo "$orig_head" > "$dotest/orig-head"
 echo "$head_name" > "$dotest/head-name"
 
 msgnum=0
-for cmt in `git rev-list --reverse --no-merges "$upstream..$orig_head"`
+for cmt in `git rev-list --reverse --no-merges "$revisions"`
 do
 	msgnum=$(($msgnum + 1))
 	echo "$cmt" > "$dotest/cmt.$msgnum"
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
new file mode 100755
index 0000000..63ec5e6
--- /dev/null
+++ b/t/t3412-rebase-root.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='git rebase --root
+
+Tests if git rebase --root --onto <newparent> can rebase the root commit.
+'
+. ./test-lib.sh
+
+test_expect_success 'prepare repository' '
+	echo 1 > A &&
+	git add A &&
+	git commit -m 1 &&
+	echo 2 > A &&
+	git add A &&
+	git commit -m 2 &&
+	git symbolic-ref HEAD refs/heads/other &&
+	rm .git/index &&
+	rm A &&
+	echo 3 > B &&
+	git add B &&
+	git commit -m 3 &&
+	echo 4 > B &&
+	git add B &&
+	git commit -m 4
+'
+
+test_expect_success 'rebase --root expects --onto' '
+	test_must_fail git rebase --root
+'
+
+cat > expect <<EOF
+4
+3
+2
+1
+EOF
+
+test_expect_success 'rebase --root --onto <newbase>' '
+	git checkout -b work &&
+	git rebase --root --onto master &&
+	git log --pretty=tformat:"%s" > rebased &&
+	test_cmp expect rebased
+'
+
+test_expect_success 'rebase --root --onto <newbase> <branch>' '
+	git branch work2 other &&
+	git rebase --root --onto master work2 &&
+	git log --pretty=tformat:"%s" > rebased2 &&
+	test_cmp expect rebased2
+'
+
+test_done
-- 
1.6.1.20.g7f5c5.dirty

^ permalink raw reply related

* [PATCH v2 2/3] rebase -i: learn to rebase root commit
From: Thomas Rast @ 2008-12-30 12:29 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <7b2902d36a4790670f20f786d4ea2e26052a6e71.1230639970.git.trast@student.ethz.ch>

Teach git-rebase -i a new option --root, which instructs it to rebase
the entire history leading up to <branch>.  This is mainly for
symmetry with ordinary git-rebase; it cannot be used to edit the root
commit in-place (it requires --onto).

In the normal mode of operation, this is fairly straightforward.  We
run cherry-pick in a loop, and cherry-pick has supported picking the
root commit since f95ebf7 (Allow cherry-picking root commits,
2008-07-04).

In --preserve-merges mode, we track the mapping from old to rewritten
commits and use it to update the parent list of each commit.  In this
case, we define 'rebase -i -p --root --onto $onto $branch' to rewrite
the parent list of all root commit(s) on $branch to contain $onto
instead.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

Changes since v1: also supports -p --root, with tests.

 git-rebase--interactive.sh |   99 +++++++++++++++++++++++++++++++------------
 t/t3412-rebase-root.sh     |   82 ++++++++++++++++++++++++++++++++++++
 2 files changed, 153 insertions(+), 28 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index c8b0861..d6f54eb 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -27,6 +27,7 @@ continue           continue rebasing process
 abort              abort rebasing process and restore original branch
 skip               skip current patch and continue rebasing process
 no-verify          override pre-rebase hook from stopping the operation
+root               rebase all reachable commmits up to the root(s)
 "
 
 . git-sh-setup
@@ -44,6 +45,7 @@ STRATEGY=
 ONTO=
 VERBOSE=
 OK_TO_SKIP_PRE_REBASE=
+REBASE_ROOT=
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -154,6 +156,11 @@ pick_one () {
 	output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
 	test -d "$REWRITTEN" &&
 		pick_one_preserving_merges "$@" && return
+	if test ! -z "$REBASE_ROOT"
+	then
+		output git cherry-pick "$@"
+		return
+	fi
 	parent_sha1=$(git rev-parse --verify $sha1^) ||
 		die "Could not get the parent of $sha1"
 	current_sha1=$(git rev-parse --verify HEAD)
@@ -197,7 +204,11 @@ pick_one_preserving_merges () {
 
 	# rewrite parents; if none were rewritten, we can fast-forward.
 	new_parents=
-	pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)"
+	pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)"
+	if test "$pend" = " "
+	then
+		pend=" root"
+	fi
 	while [ "$pend" != "" ]
 	do
 		p=$(expr "$pend" : ' \([^ ]*\)')
@@ -443,6 +454,7 @@ get_saved_options () {
 	test -d "$REWRITTEN" && PRESERVE_MERGES=t
 	test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
 	test -f "$DOTEST"/verbose && VERBOSE=t
+	test ! -s "$DOTEST"/upstream && REBASE_ROOT=t
 }
 
 while test $# != 0
@@ -547,6 +559,9 @@ first and then run 'git rebase --continue' again."
 	-i)
 		# yeah, we know
 		;;
+	--root)
+		REBASE_ROOT=t
+		;;
 	--onto)
 		shift
 		ONTO=$(git rev-parse --verify "$1") ||
@@ -555,7 +570,7 @@ first and then run 'git rebase --continue' again."
 	--)
 		shift
 		run_pre_rebase_hook ${1+"$@"}
-		test $# -eq 1 -o $# -eq 2 || usage
+		test ! -z "$REBASE_ROOT" -o $# -eq 1 -o $# -eq 2 || usage
 		test -d "$DOTEST" &&
 			die "Interactive rebase already started"
 
@@ -566,15 +581,22 @@ first and then run 'git rebase --continue' again."
 
 		require_clean_work_tree
 
-		UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
-		test -z "$ONTO" && ONTO=$UPSTREAM
+		if test -z "$REBASE_ROOT"
+		then
+			UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
+			test -z "$ONTO" && ONTO=$UPSTREAM
+			shift
+		else
+			test -z "$ONTO" &&
+				die "You must specify --onto when using --root"
+		fi
 
-		if test ! -z "$2"
+		if test ! -z "$1"
 		then
-			output git show-ref --verify --quiet "refs/heads/$2" ||
-				die "Invalid branchname: $2"
-			output git checkout "$2" ||
-				die "Could not checkout $2"
+			output git show-ref --verify --quiet "refs/heads/$1" ||
+				die "Invalid branchname: $1"
+			output git checkout "$1" ||
+				die "Could not checkout $1"
 		fi
 
 		HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
@@ -598,12 +620,19 @@ first and then run 'git rebase --continue' again."
 			# This ensures that commits on merged, but otherwise
 			# unrelated side branches are left alone. (Think "X"
 			# in the man page's example.)
-			mkdir "$REWRITTEN" &&
-			for c in $(git merge-base --all $HEAD $UPSTREAM)
-			do
-				echo $ONTO > "$REWRITTEN"/$c ||
+			if test -z "$REBASE_ROOT"
+			then
+				mkdir "$REWRITTEN" &&
+				for c in $(git merge-base --all $HEAD $UPSTREAM)
+				do
+					echo $ONTO > "$REWRITTEN"/$c ||
+						die "Could not init rewritten commits"
+				done
+			else
+				mkdir "$REWRITTEN" &&
+				echo $ONTO > "$REWRITTEN"/root ||
 					die "Could not init rewritten commits"
-			done
+			fi
 			# No cherry-pick because our first pass is to determine
 			# parents to rewrite and skipping dropped commits would
 			# prematurely end our probe
@@ -613,12 +642,21 @@ first and then run 'git rebase --continue' again."
 			MERGES_OPTION="--no-merges --cherry-pick"
 		fi
 
-		SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
 		SHORTHEAD=$(git rev-parse --short $HEAD)
 		SHORTONTO=$(git rev-parse --short $ONTO)
+		if test -z "$REBASE_ROOT"
+			# this is now equivalent to ! -z "$UPSTREAM"
+		then
+			SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
+			REVISIONS=$UPSTREAM...$HEAD
+			SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD
+		else
+			REVISIONS=$HEAD
+			SHORTREVISIONS=$SHORTHEAD
+		fi
 		git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
 			--abbrev=7 --reverse --left-right --topo-order \
-			$UPSTREAM...$HEAD | \
+			$REVISIONS | \
 			sed -n "s/^>//p" | while read shortsha1 rest
 		do
 			if test t != "$PRESERVE_MERGES"
@@ -626,14 +664,19 @@ first and then run 'git rebase --continue' again."
 				echo "pick $shortsha1 $rest" >> "$TODO"
 			else
 				sha1=$(git rev-parse $shortsha1)
-				preserve=t
-				for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
-				do
-					if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
-					then
-						preserve=f
-					fi
-				done
+				if test -z "$REBASE_ROOT"
+				then
+					preserve=t
+					for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
+					do
+						if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
+						then
+							preserve=f
+						fi
+					done
+				else
+					preserve=f
+				fi
 				if test f = "$preserve"
 				then
 					touch "$REWRITTEN"/$sha1
@@ -647,11 +690,11 @@ first and then run 'git rebase --continue' again."
 		then
 			mkdir "$DROPPED"
 			# Save all non-cherry-picked changes
-			git rev-list $UPSTREAM...$HEAD --left-right --cherry-pick | \
+			git rev-list $REVISIONS --left-right --cherry-pick | \
 				sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks
 			# Now all commits and note which ones are missing in
 			# not-cherry-picks and hence being dropped
-			git rev-list $UPSTREAM..$HEAD |
+			git rev-list $REVISIONS |
 			while read rev
 			do
 				if test -f "$REWRITTEN"/$rev -a "$(grep "$rev" "$DOTEST"/not-cherry-picks)" = ""
@@ -660,7 +703,7 @@ first and then run 'git rebase --continue' again."
 					# not worthwhile, we don't want to track its multiple heads,
 					# just the history of its first-parent for others that will
 					# be rebasing on top of it
-					git rev-list --parents -1 $rev | cut -d' ' -f2 > "$DROPPED"/$rev
+					git rev-list --parents -1 $rev | cut -d' ' -s -f2 > "$DROPPED"/$rev
 					short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)
 					grep -v "^[a-z][a-z]* $short" <"$TODO" > "${TODO}2" ; mv "${TODO}2" "$TODO"
 					rm "$REWRITTEN"/$rev
@@ -670,7 +713,7 @@ first and then run 'git rebase --continue' again."
 		test -s "$TODO" || echo noop >> "$TODO"
 		cat >> "$TODO" << EOF
 
-# Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
+# Rebase $SHORTREVISIONS onto $SHORTONTO
 #
 # Commands:
 #  p, pick = use commit
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
index 63ec5e6..c845dfc 100755
--- a/t/t3412-rebase-root.sh
+++ b/t/t3412-rebase-root.sh
@@ -49,4 +49,86 @@ test_expect_success 'rebase --root --onto <newbase> <branch>' '
 	test_cmp expect rebased2
 '
 
+test_expect_success 'rebase -i --root --onto <newbase>' '
+	git checkout -b work3 other &&
+	GIT_EDITOR=: git rebase -i --root --onto master &&
+	git log --pretty=tformat:"%s" > rebased3 &&
+	test_cmp expect rebased3
+'
+
+test_expect_success 'rebase -i --root --onto <newbase> <branch>' '
+	git branch work4 other &&
+	GIT_EDITOR=: git rebase -i --root --onto master work4 &&
+	git log --pretty=tformat:"%s" > rebased4 &&
+	test_cmp expect rebased4
+'
+
+test_expect_success 'rebase -i -p with linear history' '
+	git checkout -b work5 other &&
+	GIT_EDITOR=: git rebase -i -p --root --onto master &&
+	git log --pretty=tformat:"%s" > rebased5 &&
+	test_cmp expect rebased5
+'
+
+test_expect_success 'set up merge history' '
+	git checkout other^ &&
+	git checkout -b side &&
+	echo 5 > C &&
+	git add C &&
+	git commit -m 5 &&
+	git checkout other &&
+	git merge side
+'
+
+sed 's/#/ /g' > expect-side <<'EOF'
+*   Merge branch 'side' into other
+|\##
+| * 5
+* | 4
+|/##
+* 3
+* 2
+* 1
+EOF
+
+test_expect_success 'rebase -i -p with merge' '
+	git checkout -b work6 other &&
+	GIT_EDITOR=: git rebase -i -p --root --onto master &&
+	git log --graph --topo-order --pretty=tformat:"%s" > rebased6 &&
+	test_cmp expect-side rebased6
+'
+
+test_expect_success 'set up second root and merge' '
+	git symbolic-ref HEAD refs/heads/third &&
+	rm .git/index &&
+	rm A B C &&
+	echo 6 > D &&
+	git add D &&
+	git commit -m 6 &&
+	git checkout other &&
+	git merge third
+'
+
+sed 's/#/ /g' > expect-third <<'EOF'
+*   Merge branch 'third' into other
+|\##
+| * 6
+* |   Merge branch 'side' into other
+|\ \##
+| * | 5
+* | | 4
+|/ /##
+* | 3
+|/##
+* 2
+* 1
+EOF
+
+test_expect_success 'rebase -i -p with two roots' '
+	git checkout -b work7 other &&
+	GIT_EDITOR=: git rebase -i -p --root --onto master &&
+	git log --graph --topo-order --pretty=tformat:"%s" > rebased7 &&
+	test_cmp expect-third rebased7
+'
+
 test_done
-- 
1.6.1.20.g7f5c5.dirty

^ permalink raw reply related

* Re: rebase -i: learn to rebase root commit
From: Thomas Rast @ 2008-12-30 12:23 UTC (permalink / raw)
  To: git; +Cc: Boyd Stephen Smith Jr.
In-Reply-To: <200812291621.35732.bss@iguanasuicide.net>

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

Boyd Stephen Smith Jr. wrote:
> Here's the interpretation that *I* come up with for -p --root used together:
> The commit with no parents (OLD_ROOT) is rebased as if -p were not given, call 
> the resulting commit NEW_ROOT.  Then, the rebase continues as if "--onto 
> NEW_ROOT OLD_ROOT <branch>" was specified instead of "--onto=NEW_ROOT^ --root 
> <branch>".

I like this logic, but it feels inconsistent as soon as there are
several root commits.  (This may be somewhat academic, since any repo
with several roots should also be able to cope with a merge...)

Some digging into the -p code shows that it knows which commits were
rewritten, and which were untouched.  It rewrites such that _all_
commits in $(git merge-base --all $branch $upstream) are rewritten to
look like $onto instead, i.e., all their occurrences in parent lists
of commits are rewritten to $onto.  All other commits are only
rewritten if they have a parent that was rewritten.

So I think one sane way is to define a virtual parent 'root', and
think of parentless commits as having the (sole) parent 'root'.  Then
we can rewrite such that 'root' becomes $onto, i.e., all occurrences
of 'root' in parent lists become $onto, consistent with the normal
operation.  (For the other commits, the same rule as above is
applied.)

Of course this just boils down to saying that _all_ root commits
reachable from $branch are rewritten to have $onto as their parent.
Subsequently, all other commits will also be rewritten because they
all must have at least one rewritten parent.

> Basically, --root only changes how the first commit is handled, which I think 
> is consistent with other uses of --root.  It's also similar to cherry-picking 
> the first commit, follwed by a non-root rebase, which I think is also 
> consistent with the intention of --root.

I believe this remark still holds if there is only a single root
commit on $branch.

I will reroll with an updated 2/3 shortly.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: for newbs = little exercise / tutorial / warmup for windows and other non-sophisticated new Git users :-)
From: Zorba @ 2008-12-30 12:19 UTC (permalink / raw)
  To: git
In-Reply-To: <3ab397d0812292133r7955e892g6c19ca46629e7103@mail.gmail.com>

> I have been using $ git reset --hard <version> as an escalator to ascend /
> descend the versions up and down

you should probably be using git checkout for this

> Surely it doesn't alter the history, as I can commit versionA, versionB,
> versionC, and then reset to A, then reset to C, then reset to B.

i does alter the history.  i think this works because git isnt'
deleting the actual blob objects in the git dir until you use the git
prune, or gc or whatever (i never use it anyway).  but, you are
altering history, and just happen to be recovering.

** Ok!, so after commit B1, versionA doesn't store a link to versionB 
natively on and of its own accord. In other words BA and C are now written 
OUT of the history, as you say. I'm relying on some cached meta data that 
allows me to go back up the version tree again (ie downstream) and write B 
and/or C back into the history, which I should not rely on having access to 
all the time. Now I'm understanding more about differences between git-reset 
and git-checkout

> so when I reset to A, I've still got the ability to get to B or C again

with an uneasy conscience ;)

** yes, if the metadata cache failed or got wiped, I'd be screwed for 
getting back to later commits
I see !
I'm relying on something that isn't part of the intrinsic design... hmmm

> Now I appreciate that if I commit a new change from versionA (lets call it
> B1), then HEAD is now at B1, and B, C etc are lost, correct ?

yes! but this is not true if you had done a git checkout (there are
measures to recover B and C, provided you haven't done a prune.  i
think git reflog has some answers here, but i'm still a newbie).

> Its pertinent to where I am right now, as I've goofed a commit, and want 
> to
> reset, and commit again but I'm worried about leaveing garbage lying 
> around
> (the commits for version B and C in the example above).

you've goofed what commit (a1?, c?, d3?)?  where are you now and what
do you want to do now? reset to what version?  if you're just worried
about space used by B and C, i think git prune will purge these (look
at man page, don't guess at the syntax).

** I goofed B, so I reset to A, and redid the edits correctly this time 
(using your tip from other post $ git add -A = thanks again!), so now am on 
B1.
Having read your notes, I am now comfortable about letting B and C hang 
around, as I realise now they are out of the official picture. Sitaram's 
comparison of a linked list helps since there is no branch/merge: B1 can 
only have one parent, which is A, so A can only have one child which is B1 
(and B and C are relying on the cached stuff to survive, so let 'em freeze 
!)

i half suspect that you want to git branch at some point, but if
yo'ure just recretaing the other code bases' history form other files,
you shouldn't be able to break too much by git reset --hard, or git
prune.

** yes I might well want to at some point, but don't want to run before 
walking. I'm the only one on this project currently, and still archiving old 
versions into git. When I get the latest one in, I may branch so I can work 
away without affecting a stable master branch.

^ permalink raw reply

* Re: [PATCH] builtin-shortlog.c: use string_list_append() instead of duplicating its code
From: Johannes Schindelin @ 2008-12-30 12:20 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git, gitster
In-Reply-To: <1230136476-11081-1-git-send-email-dato@net.com.org.es>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 557 bytes --]

Hi,

On Wed, 24 Dec 2008, Adeodato Simó wrote:

> Also, when clearing the "onelines" string lists, do not free the "util"
> member: with string_list_append() is not initialized to any value (and
> was being initialized to NULL previously anyway).
> 
> NB: The duplicated code in builtin-shortlog.c predated the appearance of
> string_list_append().
> 
> Signed-off-by: Adeodato Simó <dato@net.com.org.es>

FWIW I like the patch, but would like it even more if the strdup() removal 
was squashed in (with an explanation in the commit message).

Ciao,
Dscho

^ permalink raw reply

* Re: why still no empty directory support in git
From: Johannes Schindelin @ 2008-12-30 12:09 UTC (permalink / raw)
  To: Ping Yin; +Cc: Git Mailing List
In-Reply-To: <46dff0320812291942y6aeec941k9394586621e9151b@mail.gmail.com>

Hi,

On Tue, 30 Dec 2008, Ping Yin wrote:

> Yes, i know this topic has been discussed for many times.

We have empty directory support in Git.  It works like this: for 
directories that you do want to keep, you add an empty .gitignore file.

No problem at all,
Dscho

^ permalink raw reply

* Re: [PATCH] t7500-commit.sh: do not call test_set_editor unnecessarily, it's confusing
From: Johannes Schindelin @ 2008-12-30 12:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Adeodato Simó
In-Reply-To: <7vmyefco11.fsf@gitster.siamese.dyndns.org>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 839 bytes --]

Hi,

On Mon, 29 Dec 2008, Junio C Hamano wrote:

> Adeodato Simó <dato@net.com.org.es> writes:
> 
> > I was reading this test case, and it took a small bit to figure out 
> > the editor was not being used at all. I hope there was no hidden 
> > reason for it to be there, and it can go away.
> 
> That 'zort' came from 1320857 (builtin-commit: fix --signoff, 
> 2007-11-11), and I _think_ it is trying to make sure that presense of 
> "-F -" makes the editor not to trigger.
> 
> Dscho?

Hmm.  Obviously, I failed to document properly why I tested the editor, 
but I think it makes sense to assume that -F still triggered an 
interactive editor at some stage in the development of builtin commit.

I do not have anything against separating that issue into another test 
case, but I am strongly opposed to simply removing it.

Ciao,
Dscho

^ permalink raw reply

* Re: is there an easier way to do this ? [Scanned]
From: Zorba @ 2008-12-30 12:00 UTC (permalink / raw)
  To: git
In-Reply-To: <3ab397d0812292132h6ffe7e49o650fbf35588666db@mail.gmail.com>

Hi Jeff,

Thanks for that, and yes, I will be more careful with my postings. There is 
already so much traffic on this list, the last thing anyone needs is more 
fragmentation.

I'm so chuffed now that I got $ git add -A (don't even need the dot, i read 
!) $ git commit !
Thank you !

I was up till 5:30am this morning working on this. Another in a series of 
late nights. My partner stuck her head round the door at 4 and at 5 and 
looked at me like I've flipped out (gone crazy). I think she's gonna try and 
get them to take me away, so I've only got limited time to "get git" :-)

Its exactly what I need for versioning off my project where the file 
"portfolio" (i.e. the configuration of the containers) changes every version 
(probably the containers change more than content - I know, badly written, 
but hey, that's all in the past)

On another note - your name is very resonant of this part of the world 
(Northern Ireland) - I'm guessing you're from here or have some roots here ?

"Jeff Whiteside" <jeff.m.whiteside@gmail.com> wrote in message 
news:3ab397d0812292132h6ffe7e49o650fbf35588666db@mail.gmail.com...
> you should reply to the original thread, so that you don't create a
> new one.  makes it almost impossible to find what you're referencing.
>
> also, don't bother with git-rm.  a simple rm is the same thing.
> (committing will notice that this file is gone)
>
> On Mon, Dec 29, 2008 at 8:29 PM, Zorba <cr@altmore.co.uk> wrote:
>> (punches air with fist)
>> yes indeed !
>>
>> sorry, I didn't follow up on the --update flag first time
>>
>> $ git add -A .
>> $ git commit
>>
>> home in a boat!
>>
>> "Jacob Helwig" <jacob.helwig@gmail.com> wrote in message
>> news:8c9a060812292017m600ca246pf8660630d49a7067@mail.gmail.com...
>>> On Mon, Dec 29, 2008 at 20:11, Conor Rafferty
>>> <conor.rafferty@altmore.co.uk> wrote:
>>>> Ah, but what about the files that have been removed from this version ?
>>>> - that's the whole point of doing commit -a, so I don't have to spend
>>>> ages doing diffs to produce a list of files to feed into git-rm
>>>>
>>>> Or have I missed another glarer ?
>>>>
>>>> -----Original Message-----
>>>> From: Jacob Helwig [mailto:jacob.helwig@gmail.com]
>>>> Sent: 30 December 2008 04:01
>>>> To: git@vger.kernel.org
>>>> Cc: Conor Rafferty
>>>> Subject: Re: is there an easier way to do this ? [Scanned]
>>>>
>>>> On Mon, Dec 29, 2008 at 19:51, Zorba <cr@altmore.co.uk> wrote:
>>>>> The manual shows you can SHOW untracked files, but not add them as
>>>>> part of the commit -a jig
>>>>>
>>>>> Seems a bit strange that git-add operates on both exisging and new
>>>>> files when used standalone, but its behaviour changes when
>>>>> encapsulated in commit -a...
>>>>>
>>>>> So, I thought maybe $ git commit -a, then $ git add .
>>>>> but then the files tracked have missed the commit boat they were meant
>>>>
>>>>> to be on, haven't they,
>>>>>
>>>>> hang on -
>>>>> what about
>>>>>
>>>>> $ git add .
>>>>> $ git commit -a
>>>>>
>>>>> I do believe I've cracked it
>>>>> if so, it seems a bit wasteful, 2x adds (one explicti and one embedded
>>>>
>>>>> in -a) ? shame on you linux kernel guys, i'd have expected better :-)
>>>>>
>>>>> "Zorba" <cr@altmore.co.uk> wrote in message
>>>>> news:gjc52u$ehc$4@ger.gmane.org...
>>>>>> ok, now I'm in this for real, archiving versions of our website
>>>>>> project (5k files approx)
>>>>>>
>>>>>> so here is the workflow:
>>>>>>
>>>>>> - copy version 1 files into GIT dir
>>>>>>
>>>>>> - open git bash
>>>>>>
>>>>>> $ git init
>>>>>>
>>>>>> $ git add .
>>>>>>
>>>>>> $ git commit -m "version1"
>>>>>>
>>>>>> all vanilla ? cool
>>>>>> next job = store version 2, so delete version 1 files from GIT dir,
>>>>>> copy in version 2
>>>>>> version2 has different files from 1 - which ones? Out of 5k files
>>>>>> could be 1% = 50 new ones, and same amount removed. Why should I
>>>>>> care, with such a powerful friend as git around, n'est pas?
>>>>>> THIS TIME we are going to be CLEVER and use "-a" flag on commit to
>>>>>> pick up any files that have been REMOVED (or "deleted" in git-speak)
>>>>>>
>>>>>> $ git commit -a -m "version2"
>>>>>>
>>>>>> BUT this does not pick up any new ones that have been added,
>>>>>>
>>>>>> and when we run
>>>>>>
>>>>>> $ git status > ../git_status.txt
>>>>>>
>>>>>> these are referred to as "untracked files"
>>>>>> only problem there are 50 ish
>>>>>> is there not another flag on git commit to treat any untracked file
>>>>>> as a new file ?
>>>>>> (would save me typing or creating a list out of these untracked ones
>>>>>> and feeding them into git add)
>>>>>>
>>>>>> I know, I realise now I should have looked up git-commit in the
>>>>>> manual - in case its not there, pls enlighten me !
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> 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
>>>>>
>>>>
>>>> If you do an explicit git add, then you don't need the -a on git 
>>>> commit,
>>>> since everything you want to commit will already be in the index for 
>>>> git
>>>> commit to work with.
>>>>
>>>
>>> See the -A flag for git add (and it's reference to --update).  -A will
>>> remove files that have been removed, add untracked, and update ones
>>> that have changed, all in one go.
>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> 

^ permalink raw reply

* Re: many git sites homepages megabytes big
From: Anders Melchiorsen @ 2008-12-30 11:01 UTC (permalink / raw)
  To: git; +Cc: Jakub Narebski, jidanni, pasky
In-Reply-To: <m31vvqcvzp.fsf@localhost.localdomain>

Jakub Narebski wrote:
> jidanni@jidanni.org writes:
>
>   
>> I notice the web interfaces to many git sites are very risky to just
>> click on. E.g., just clicking http://repo.or.cz/ sends megabytes to
>> the users browser. At least the homepage of such sites should be
>> something lighter in weight.
>>     
>
> That is a bit of historical artifact. Currently the "index" page for
> gitweb installation is 'projects_list' page with _all_ the projects
> hosted. It is not split into pages, like for example 'log' or 'heads'
> views are; there were some patches for that, but would have to be
> redone as the area changed a bit since. It could have been replaced by
> projects search page...
>
> It is a bit of historical reason.
>   

For the specific case of repo.or.cz, I guess that turning on HTTP 
compression might help a lot.


Anders.

^ permalink raw reply

* Re: git-ls-files -l
From: Jakub Narebski @ 2008-12-30 11:01 UTC (permalink / raw)
  To: jidanni; +Cc: git
In-Reply-To: <87abae6hbn.fsf@jidanni.org>

jidanni@jidanni.org writes:

> Beginners, finding git-ls-files acts like ls,
> are baffled as to why they can't go on to ls -l.
> 
> The git-ls-files man page should reveal the secret of how also to see
> file sizes. Perhaps the closest one can get is
> $ git-ls-tree -l --abbrev ...

git-ls-tree has the '-l' option mimicking (somewhat) "ls -l" behaviour
only because it was thought to be useful for gitweb (to have file
sizes in 'tree' view, like cgit has it), although gitweb doesn't use
it yet.

I think it would be easy to add '-l' also to git-ls-files. Please
remember to provide size only for blobs, as provoding size for trees
would make it harder to change to future packv4, where tree objects
would be stored deconstructed.

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH] Apply -p<value> on git-diffs that create/delete files
From: Junio C Hamano @ 2008-12-30  9:03 UTC (permalink / raw)
  To: Andrew Ruder; +Cc: git
In-Reply-To: <20081230011545.GA81224@bowser.Belkin>

Andrew Ruder <andy@aeruder.net> writes:

> diff --git a/builtin-apply.c b/builtin-apply.c
> index 07244b0..584a910 100644
> --- a/builtin-apply.c
> +++ b/builtin-apply.c
> @@ -656,137 +660,57 @@ static const char *stop_at_slash(const char *line, int llen)
>  }
>  
>  /*
> - * This is to extract the same name that appears on "diff --git"
> - * line.  We do not find and return anything if it is a rename
> - * patch, and it is OK because we will find the name elsewhere.
> + * This is to extract the same name that appears on "diff --git" line.
> + * The name that is returned also has the root applied to it and the
> + * p_value applied.  We do not find and return anything if it is a
> + * rename patch, and it is OK because we will find the name elsewhere.
>   * We need to reliably find name only when it is mode-change only,
> - * creation or deletion of an empty file.  In any of these cases,
> - * both sides are the same name under a/ and b/ respectively.
> + * creation or deletion of an empty file.  In any of these cases, both
> + * sides are the same name under a/ and b/ respectively.
>   */

This is a very good description of what the fix should do.

> +static char *git_header_name(char *line)
> ...
> -	/*
> -	 * Accept a name only if it shows up twice, exactly the same
> -	 * form.
> -	 */
> -	for (len = 0 ; ; len++) {
> -		switch (name[len]) {
> -		default:
> -			continue;
> -		case '\n':
> -			return NULL;
> -		case '\t': case ' ':
> -			second = name+len;
> -			for (;;) {
> -				char c = *second++;
> -				if (c == '\n')
> -					return NULL;
> -				if (c == '/')
> -					break;
> -			}
> -			if (second[len] == '\n' && !memcmp(name, second, len)) {
> -				return xmemdupz(name, len);
> -			}
> -		}
> -	}

You lost the above logic, and instead call find_name() with TERM_SPACE |
TERM_TAB to find the end of the first name and you expect it uniquely will
find it.  It unfortunately won't.  Consider this patch:

        diff --git a/b is file b/b is file
        index e69de29..ce01362 100644
        --- a/b is file	
        +++ b/b is file	
        @@ -0,0 +1 @@
        +hello

Your version finds "b" as the first name, skips to "is file b/b is file"
and assume that is the second name, and your new code later mistakenly
declares it as a rename and returns NULL.

> +	/* First we see if they match, if they do, we are done. */
> +	if (strcmp(first, second)) {
> +		const char *first_slash, *second_slash;
> +		/* If they don't, we check that we don't have a a/<match> b/<match>, if we
> + 		 * do we return one of those so the error messages go through correctly
> +		 * later on */
> +		first_slash = stop_at_slash(first, strlen(first));
> +		second_slash = stop_at_slash(second, strlen(second));
>  
> +		/* If this fails, it must be a rename, just return NULL */
> +		if (!first_slash || !second_slash || strcmp(first_slash, second_slash))
> +			goto error2;
>  	}

It should of course return "b is file"; the complex backgracking you
removed is all about handling this case correctly.

>  builtin-apply.c       |  203 +++++++++++++++----------------------------------
>  t/t4120-apply-popt.sh |    5 +-
>  2 files changed, 64 insertions(+), 144 deletions(-)

I really wished that this reduction of lines resulted in a code with less
bug, though.

^ permalink raw reply

* Re: why still no empty directory support in git
From: Asheesh Laroia @ 2008-12-30  8:58 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <9b18b3110812300043l55a42f6sd995f36bf857543e@mail.gmail.com>

On Tue, 30 Dec 2008, demerphq wrote:

> 2008/12/30 Asheesh Laroia <asheesh@asheesh.org>:

>> I ask about this because I'm using git to track email in Maildir 
>> repositories, and in that vein I'm getting bitten by git's removal of 
>> empty directories.
>
> Add a .exists to each directory.  There is precedent for such an 
> approach in other systems.

Delivering mail into a Maildir is a three-step process.  Let's say 
we are delivering to a Maildir spool stored in ~/Maildir.

(1)

The message is written out to ~/Maildir/tmp/some_filename.

(2)

When the message is complete, it is rename()d to 
~/Maildir/new/some_name.

(3)

When a mail user agent reads the Maildir spool, it checks new/ for new 
mail. If there is a message there, it renames it to 
~/Maildir/cur/some_other_filename and announces to the user, "You've got 
mail!"

So, let's say I take your suggestion.

$ touch ~/Maildir/new/.exists
$ git add ~/Maildir/new/.exists && git commit -m "La di da"

Now a spec-compliant Maildir user agent will attempt to deliver this new 
"email message" of zero bytes into the mail spool and assign it a message 
UID.  Doing so will remove it from Maildir/new.

Then I do "git pull" to get the new messages from my mail server's Maildir 
repository for my email.  This causes git read-tree to eventually be run. 
If the new tree has no unprocessed email, git runs rmdir() on 
~/Maildir/new/.

Now if I want to write a new email to ~/Maildir/ (such as due to copying 
an email from another folder), the Maildir user agent suddenly finds 
itself in a strange place: new/ does not exist, violating the definition 
of a Maildir. This breaks mail processing for that ~/Maildir/ folder.

This is because git is removing these directories. There is a strict 
incompatibility between git rmdir()ing empty directories behind my back 
and Maildir systems.

I hope that explains the issue I face, both to Junio and to Yves.

Note that for me, there is no issue with how to handle merging of empty 
directories, or what happens if these empty directories become files, or 
which empty directories to keep around; if git just never rmdir()s any 
directories for me, and otherwise acts identically to now, that would 
solve my problem. I can look into preparing an RFC patch that creates a 
mode like that.

-- Asheesh.

-- 
You will be the last person to buy a Chrysler.

^ permalink raw reply

* Re: why still no empty directory support in git
From: demerphq @ 2008-12-30  8:43 UTC (permalink / raw)
  To: Asheesh Laroia; +Cc: Git Mailing List
In-Reply-To: <alpine.DEB.2.00.0812300113050.22107@vellum.laroia.net>

2008/12/30 Asheesh Laroia <asheesh@asheesh.org>:
> On Tue, 30 Dec 2008, Asheesh Laroia wrote:
>
>> On Tue, 30 Dec 2008, Ping Yin wrote:
>>
>>> 2. unclear logic, for example, whether to remove the directory after the
>>> last file in it is deleted
>>
>> This is the thing I dislike most about git: that it sometimes calls
>> rmdir() for me.  At least, one should be able to turn it off in a
>> per-repository basis.  I'm going to see how hard a patch that would be to
>> write.
>
> Well, changing this behavior seems to be "as easy as" changing unlink_entry
> in unpack_trees.c to not always rmdir(). The most naive thing I can think of
> is to have unlink_entry in unpack_trees check against the git config. It's
> probably more sensible for unpack_trees to be passed an argument that
> determines if it rmdir()s; that argument could be set via argv at "git
> unpack-tree" time, which could be set out of a configuration value read at
> "git" time.
>
> Would a change of the "more sensible" kind possibly be accepted by the git
> maintainer?
>
> I ask about this because I'm using git to track email in Maildir
> repositories, and in that vein I'm getting bitten by git's removal of empty
> directories.

Add a .exists to each directory.  There is precedent for such an
approach in other systems.

cheers,
Yves


-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

^ permalink raw reply

* Re: rebase -i: learn to rebase root commit
From: Junio C Hamano @ 2008-12-30  8:22 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git
In-Reply-To: <200812292249.45900.trast@student.ethz.ch>

Thomas Rast <trast@student.ethz.ch> writes:

> ... is there any sensible
> use/interpretation of -p --root that I'm missing?  Or should it just
> disallow this combination?

If --root is about replaying all the history, wouldn't people want to use
it together with -p to reconstruct the whole history as a substitute for
filter-branch?  IOW, I have a suspicion that they most likely should go
together.

I never felt a need to rebase deep down to --root myself anyway, so I am a
bad judge for people's needs on this topic, though.

^ permalink raw reply

* Re: [PATCH] doc/git-send-email: mention sendemail.cc config variable
From: Junio C Hamano @ 2008-12-30  8:00 UTC (permalink / raw)
  To: markus.heidelberg; +Cc: Thomas Rast, git
In-Reply-To: <200812291429.01822.markus.heidelberg@web.de>

Markus Heidelberg <markus.heidelberg@web.de> writes:

> It is already in next, I think a following patch should be against next
> now, shouldn't it?

Surely, and thanks.

If you look at the output of

	$ git log --first-parent origin/master..origin/next

You will find the tip of mh/maint-sendmail-cc-doc topic branch is at
bd7c6e7 (doc/git-send-email: mention sendemail.cc config variable,
2008-12-29).  I'll apply any follow-up patch to the topic on top of that
commit, and then merge the result to 'next' (and 'master'/'maint' when the
result is ready).

In rare cases when there are other topics in 'next' that touch vicinity of
the code you are modifying, a patch made against 'next' may not apply
cleanly to the topic, but I'll wiggle it to apply anyway (that is what the
maintainers do), so it would certainly be nicer if you sent a patch to the
tip of the topic you are updating, but there is no need to worry about
such conflicts too much.

^ permalink raw reply

* Re: why still no empty directory support in git
From: Junio C Hamano @ 2008-12-30  7:45 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: Jeff Whiteside, Asheesh Laroia, Git Mailing List
In-Reply-To: <200812300758.41988.robin.rosenberg.lists@dewire.com>

Robin Rosenberg <robin.rosenberg.lists@dewire.com> writes:

> You can have an empty tree, but the index doesn't store them, so they
> would be lost on checkout/commit. Linus sketched a solution, but nobody
> took the bait. Seems doable if anyone really wants it, but I'm certain
> it adds a lot of special cases.

I think the original poster covered that "a lot of special cases" as
"unclear semantics", and there are more.  Do you want to have the presense
of empty directory "sticky"?  Perhaps it later becomes non-empty at some
point; will the "will always present" attribute kept then?  What happens
when such a directory becomes empty later?  What should happen when a
branch that has such a directory with "sticky existence" and another
branch with the same directory but without the stickiness are merged?

But I think one bigger reason missing from the list is that many people
loudly talked about "wants", but nobody made convincing argument on
"needs" of such a feature.

^ permalink raw reply

* Re: why still no empty directory support in git
From: Robin Rosenberg @ 2008-12-30  6:58 UTC (permalink / raw)
  To: Jeff Whiteside; +Cc: Asheesh Laroia, Git Mailing List
In-Reply-To: <3ab397d0812292128j65e2e1e1xf403a998f4653aac@mail.gmail.com>

tisdag 30 december 2008 06:28:58 skrev Jeff Whiteside:
> funny, i thought it was 1, by design.
Sure, but designs can be changed.

> 
> but i forget why a tree object couldn't point to an empty blob.

It can, but that's not the same.

You can have an empty tree, but the index doesn't store them, 
so they would be lost on checkout/commit. Linus sketched a solution, 
but nobody took the bait. Seems doable if anyone really wants it, but
I'm certain it adds a lot of special cases.

Look for a discussion [RFC PATCH] Re: Empty directories... posted on 2007-07-19.
It's in the middle of a long thread.

-- robin

^ permalink raw reply

* Re: why still no empty directory support in git
From: Asheesh Laroia @ 2008-12-30  6:25 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <alpine.DEB.2.00.0812300008060.31590@vellum.laroia.net>

On Tue, 30 Dec 2008, Asheesh Laroia wrote:

> On Tue, 30 Dec 2008, Ping Yin wrote:
>
>> 2. unclear logic, for example, whether to remove the directory after the 
>> last file in it is deleted
>
> This is the thing I dislike most about git: that it sometimes calls rmdir() 
> for me.  At least, one should be able to turn it off in a per-repository 
> basis.  I'm going to see how hard a patch that would be to write.

Well, changing this behavior seems to be "as easy as" changing 
unlink_entry in unpack_trees.c to not always rmdir(). The most naive thing 
I can think of is to have unlink_entry in unpack_trees check against the 
git config. It's probably more sensible for unpack_trees to be passed an 
argument that determines if it rmdir()s; that argument could be set via 
argv at "git unpack-tree" time, which could be set out of a configuration 
value read at "git" time.

Would a change of the "more sensible" kind possibly be accepted by the git 
maintainer?

I ask about this because I'm using git to track email in Maildir 
repositories, and in that vein I'm getting bitten by git's removal of 
empty directories.

-- Asheesh.

-- 
You will gain money by an illegal action.

^ permalink raw reply

* Re: why still no empty directory support in git
From: Liu Yubao @ 2008-12-30  6:09 UTC (permalink / raw)
  To: Ping Yin; +Cc: Git Mailing List
In-Reply-To: <46dff0320812291942y6aeec941k9394586621e9151b@mail.gmail.com>

Ping Yin wrote:
> Yes, i know this topic has been discussed for many times. However, i
> am still not clear about the real reason.
> 
> So which is the reason?
> 
> 1. it's by design, intentional
It's saied somewhere git is a "stupid content tracker", it cares file content
not file name, and empty directories will complicate the merge algorithm
unnecessarily.

> 2. unclear logic, for example, whether to remove the directory after
> the last file in it is deleted
> 3. hard work, no one has picked it yet
> 4. hardly done in current model
> 
> Ping Yin

^ permalink raw reply

* Re: for newbs = little exercise / tutorial / warmup for windows and other non-sophisticated new Git users :-)
From: Sitaram Chamarty @ 2008-12-30  5:34 UTC (permalink / raw)
  To: git
In-Reply-To: <gjc7qa$jdj$4@ger.gmane.org>

Hi Conor,

On 2008-12-30, Zorba <cr@altmore.co.uk> wrote:
> so when I reset to A, I've still got the ability to get to B or C again

if this is true...  (call this case 1)

> Now I appreciate that if I commit a new change from versionA (lets call it 
> B1), then HEAD is now at B1, and B, C etc are lost, correct ?

...then this (call this case 2) is not true.

In case 1, *how* do you get back to B and C?  However you do
it, the same action will get you to B and C *after* you
created B1 as well.

It might help to think of these things loosely using a
malloc/linked-list analogy.  Imagine a singly-linked list,
and a variable in your program called "head" pointing to the
top element.  Each element contains a back-pointer to its
parent.  You can start from head and walk the list backward,
but you can't walk forward -- there are no forward pointers.

A "git commit" is analogous to:
    newblkptr = malloc(...);
    ... store whatever you want in the new block ...
    newblkptr.backptr = head;
    head = newblkptr;

i.e., a classic linked list add.

A "git reset --hard HEAD^" essentially pops the topmost
element off the list:
    head = head.backptr

A "git checkout -f HEAD^" is like walking a linked list
backward in a loop, and stopping at some intermediate block
to do something -- other the temporary loop-variable,
nothing else (no global variable perhaps) points to this
block, so this is like a detached head.

Of course, nothing prevents you from permanently saving this
temporary loop variable because you suddenly realise *this*
link in the chain is very important for the rest of your
program:
    some_global_var = temp_blk_ptr;

This is like "git checkout -b newbranch" does.

> Its pertinent to where I am right now, as I've goofed a commit, and want to 
> reset, and commit again but I'm worried about leaveing garbage lying around 
> (the commits for version B and C in the example above).

(1) never worry about leaving garbage around; there are many
operations that do that; it's part of the design.  Don't
sweat it.

(2) when in doubt, try "gitk --all".  That's a good GUI.
I'm normally a CLI freak, but when something needs to be
understood/learnt, a well-designed GUI really helps.

Run "gitk --all" on the side and hit F5 on it after each
operation on the command line -- helped me when I was trying
to figure out what's happening.

PS: although it doesn't mention detached heads,
http://eagain.net/articles/git-for-computer-scientists/
helped me a lot...

^ permalink raw reply

* Re: for newbs = little exercise / tutorial / warmup for windows and other non-sophisticated new Git users :-)
From: Jeff Whiteside @ 2008-12-30  5:33 UTC (permalink / raw)
  To: Zorba; +Cc: git
In-Reply-To: <gjc7qa$jdj$4@ger.gmane.org>

> Thanks for your contrib. I'll pick these up for sure, but right now I'm
> despo to make some progress getting this confounded real-life project
> versioned.

np, i do understand totally.

> I've just made a commit I want to retract.

this is the purpose of git reset --soft/mixed/hard

> I have been using $ git reset --hard <version> as an escalator to ascend /
> descend the versions up and down

you should probably be using git checkout for this

> Surely it doesn't alter the history, as I can commit versionA, versionB,
> versionC, and then reset to A, then reset to C, then reset to B.

i does alter the history.  i think this works because git isnt'
deleting the actual blob objects in the git dir until you use the git
prune, or gc or whatever (i never use it anyway).  but, you are
altering history, and just happen to be recovering.

> so when I reset to A, I've still got the ability to get to B or C again

with an uneasy conscience ;)

> Now I appreciate that if I commit a new change from versionA (lets call it
> B1), then HEAD is now at B1, and B, C etc are lost, correct ?

yes! but this is not true if you had done a git checkout (there are
measures to recover B and C, provided you haven't done a prune.  i
think git reflog has some answers here, but i'm still a newbie).

> Its pertinent to where I am right now, as I've goofed a commit, and want to
> reset, and commit again but I'm worried about leaveing garbage lying around
> (the commits for version B and C in the example above).

you've goofed what commit (a1?, c?, d3?)?  where are you now and what
do you want to do now? reset to what version?  if you're just worried
about space used by B and C, i think git prune will purge these (look
at man page, don't guess at the syntax).

i half suspect that you want to git branch at some point, but if
yo'ure just recretaing the other code bases' history form other files,
you shouldn't be able to break too much by git reset --hard, or git
prune.

> BTW: sdf=Syntax Definition Formalism?

hahahaha, no, i was just typing/copypasting garbage, because my gmail
woudln't' get out of bold mode and forgot to delete it at the end.
haha.

On Mon, Dec 29, 2008 at 8:24 PM, Zorba <cr@altmore.co.uk> wrote:
> Hi Jeff,
>
> Thanks for your contrib. I'll pick these up for sure, but right now I'm
> despo to make some progress getting this confounded real-life project
> versioned.
>
> But where I'm stuck now touches on your post.
>
> I've just made a commit I want to retract.
>
> I have been using $ git reset --hard <version> as an escalator to ascend /
> descend the versions up and down
> Surely it doesn't alter the history, as I can commit versionA, versionB,
> versionC, and then reset to A, then reset to C, then reset to B.
>
> so when I reset to A, I've still got the ability to get to B or C again
>
> Now I appreciate that if I commit a new change from versionA (lets call it
> B1), then HEAD is now at B1, and B, C etc are lost, correct ?
>
> Its pertinent to where I am right now, as I've goofed a commit, and want to
> reset, and commit again but I'm worried about leaveing garbage lying around
> (the commits for version B and C in the example above).
>
> NB if you read my latest posts you will see why I chose the example I did
> for my "warm-up" as it closely models what I'm trying to do for real.
>
>
> BTW: sdf=Syntax Definition Formalism?
>
> "Jeff Whiteside" <jeff.m.whiteside@gmail.com> wrote in message
> news:3ab397d0812291505v77824e6fvdecebc80f38a5f89@mail.gmail.com...
>
> -"Rollback to each of the versions, starting with version A"
> this is bad.  you're saying rollback.  to others that have used scms,
> this will mean, "retrieve an older copy", but in git, this is DELETING
> all the versions after the version that you "rollback" to.  your blog
> post shouldn't discuss the git-reset --hard command at all, since
> you're rewriting history, which is dangerous.  afaik, most scms don't
> allow you to rewrite history.  to "rollback" to an older version you
> should use checkout the git-checkout command.  maybe the git reset
> -–hard HEAD is okay to include... but it won't be immediately obvious
> to new users why it does what it does... this nomenclature was likely
> not the best choice whenever it was made.
>
>
> gl with your gitting.
>
> whiteside
>
>
>
>
> u're talking sdf
>
>
>
>
> On Sat, Dec 27, 2008 at 5:29 PM, Zorba <cr@altmore.co.uk> wrote:
>>
>> tidied up the formatting, added a few more comments where needed, fixed
>> errors/lack of clarity
>>
>> "Zorba" <cr@altmore.co.uk> wrote in message
>> news:gj68a0$u56$3@ger.gmane.org...
>> > Here is a little exercise / tutorial / warm-up for someone starting out
>> > with Git. If you're anyting like me you may find the tutorials etc. on
>> > git.or.cz a bit daunting. I recommend you try this after reading the
>> > user
>> > manual but before tearing your hair out trying to follow all the
>> > examples
>> > in the user manual. After you've followed this simple workflow, then go
>> > back to the more advanced stuff  in the tutorials and user manuals (like
>> > cloning repositories and creating and merging branches).
>> >
>> > I created this exercise to try and model our workflow and what we wanted
>> > to use git for = tracking a project with multiple files where the
>> > filebase
>> > might change frequently from one version to the next.
>> >
>> > http://siliconmouth.wordpress.com/category/nerdy/
>> >
>> > look for December 27, 2008 or "git warmup"
>> >
>> >
>>
>>
>>
>> --
>> 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
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: is there an easier way to do this ? [Scanned]
From: Jeff Whiteside @ 2008-12-30  5:32 UTC (permalink / raw)
  To: Zorba; +Cc: git
In-Reply-To: <gjc83i$juc$4@ger.gmane.org>

you should reply to the original thread, so that you don't create a
new one.  makes it almost impossible to find what you're referencing.

also, don't bother with git-rm.  a simple rm is the same thing.
(committing will notice that this file is gone)

On Mon, Dec 29, 2008 at 8:29 PM, Zorba <cr@altmore.co.uk> wrote:
> (punches air with fist)
> yes indeed !
>
> sorry, I didn't follow up on the --update flag first time
>
> $ git add -A .
> $ git commit
>
> home in a boat!
>
> "Jacob Helwig" <jacob.helwig@gmail.com> wrote in message
> news:8c9a060812292017m600ca246pf8660630d49a7067@mail.gmail.com...
>> On Mon, Dec 29, 2008 at 20:11, Conor Rafferty
>> <conor.rafferty@altmore.co.uk> wrote:
>>> Ah, but what about the files that have been removed from this version ?
>>> - that's the whole point of doing commit -a, so I don't have to spend
>>> ages doing diffs to produce a list of files to feed into git-rm
>>>
>>> Or have I missed another glarer ?
>>>
>>> -----Original Message-----
>>> From: Jacob Helwig [mailto:jacob.helwig@gmail.com]
>>> Sent: 30 December 2008 04:01
>>> To: git@vger.kernel.org
>>> Cc: Conor Rafferty
>>> Subject: Re: is there an easier way to do this ? [Scanned]
>>>
>>> On Mon, Dec 29, 2008 at 19:51, Zorba <cr@altmore.co.uk> wrote:
>>>> The manual shows you can SHOW untracked files, but not add them as
>>>> part of the commit -a jig
>>>>
>>>> Seems a bit strange that git-add operates on both exisging and new
>>>> files when used standalone, but its behaviour changes when
>>>> encapsulated in commit -a...
>>>>
>>>> So, I thought maybe $ git commit -a, then $ git add .
>>>> but then the files tracked have missed the commit boat they were meant
>>>
>>>> to be on, haven't they,
>>>>
>>>> hang on -
>>>> what about
>>>>
>>>> $ git add .
>>>> $ git commit -a
>>>>
>>>> I do believe I've cracked it
>>>> if so, it seems a bit wasteful, 2x adds (one explicti and one embedded
>>>
>>>> in -a) ? shame on you linux kernel guys, i'd have expected better :-)
>>>>
>>>> "Zorba" <cr@altmore.co.uk> wrote in message
>>>> news:gjc52u$ehc$4@ger.gmane.org...
>>>>> ok, now I'm in this for real, archiving versions of our website
>>>>> project (5k files approx)
>>>>>
>>>>> so here is the workflow:
>>>>>
>>>>> - copy version 1 files into GIT dir
>>>>>
>>>>> - open git bash
>>>>>
>>>>> $ git init
>>>>>
>>>>> $ git add .
>>>>>
>>>>> $ git commit -m "version1"
>>>>>
>>>>> all vanilla ? cool
>>>>> next job = store version 2, so delete version 1 files from GIT dir,
>>>>> copy in version 2
>>>>> version2 has different files from 1 - which ones? Out of 5k files
>>>>> could be 1% = 50 new ones, and same amount removed. Why should I
>>>>> care, with such a powerful friend as git around, n'est pas?
>>>>> THIS TIME we are going to be CLEVER and use "-a" flag on commit to
>>>>> pick up any files that have been REMOVED (or "deleted" in git-speak)
>>>>>
>>>>> $ git commit -a -m "version2"
>>>>>
>>>>> BUT this does not pick up any new ones that have been added,
>>>>>
>>>>> and when we run
>>>>>
>>>>> $ git status > ../git_status.txt
>>>>>
>>>>> these are referred to as "untracked files"
>>>>> only problem there are 50 ish
>>>>> is there not another flag on git commit to treat any untracked file
>>>>> as a new file ?
>>>>> (would save me typing or creating a list out of these untracked ones
>>>>> and feeding them into git add)
>>>>>
>>>>> I know, I realise now I should have looked up git-commit in the
>>>>> manual - in case its not there, pls enlighten me !
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> 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
>>>>
>>>
>>> If you do an explicit git add, then you don't need the -a on git commit,
>>> since everything you want to commit will already be in the index for git
>>> commit to work with.
>>>
>>
>> See the -A flag for git add (and it's reference to --update).  -A will
>> remove files that have been removed, add untracked, and update ones
>> that have changed, all in one go.
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply


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