git-rebase: add keep_empty flag
Add a command line switch to git-rebase to allow a user the ability to specify that they want to keep any commits in a series that are empty. When git-rebase's type is am, then this option will automatically keep any commit that has a tree object identical to its parent. This patch changes the default behavior of interactive rebases as well. With this patch, git-rebase -i will produce a revision set passed to git-revision-editor, in which empty commits are commented out. Empty commits may be kept manually by uncommenting them. If the new --keep-empty option is used in an interactive rebase the empty commits will automatically all be uncommented in the editor. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									bedfe86ce6
								
							
						
					
					
						commit
						90e1818f9a
					
				|  | @ -238,6 +238,10 @@ leave out at most one of A and B, in which case it defaults to HEAD. | ||||||
| 	will be reset to where it was when the rebase operation was | 	will be reset to where it was when the rebase operation was | ||||||
| 	started. | 	started. | ||||||
|  |  | ||||||
|  | --keep-empty:: | ||||||
|  | 	Keep the commits that do not change anything from its | ||||||
|  | 	parents in the result. | ||||||
|  |  | ||||||
| --skip:: | --skip:: | ||||||
| 	Restart the rebasing process by skipping the current patch. | 	Restart the rebasing process by skipping the current patch. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -20,11 +20,20 @@ esac | ||||||
|  |  | ||||||
| test -n "$rebase_root" && root_flag=--root | test -n "$rebase_root" && root_flag=--root | ||||||
|  |  | ||||||
| git format-patch -k --stdout --full-index --ignore-if-in-upstream \ | if test -n "$keep_empty" | ||||||
| 	--src-prefix=a/ --dst-prefix=b/ \ | then | ||||||
| 	--no-renames $root_flag "$revisions" | | 	# we have to do this the hard way.  git format-patch completely squashes | ||||||
| git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" && | 	# empty commits and even if it didn't the format doesn't really lend | ||||||
| move_to_original_branch | 	# itself well to recording empty patches.  fortunately, cherry-pick | ||||||
|  | 	# makes this easy | ||||||
|  | 	git cherry-pick --allow-empty "$revisions" | ||||||
|  | else | ||||||
|  | 	git format-patch -k --stdout --full-index --ignore-if-in-upstream \ | ||||||
|  | 		--src-prefix=a/ --dst-prefix=b/ \ | ||||||
|  | 		--no-renames $root_flag "$revisions" | | ||||||
|  | 	git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" | ||||||
|  | fi && move_to_original_branch | ||||||
|  |  | ||||||
| ret=$? | ret=$? | ||||||
| test 0 != $ret -a -d "$state_dir" && write_basic_state | test 0 != $ret -a -d "$state_dir" && write_basic_state | ||||||
| exit $ret | exit $ret | ||||||
|  |  | ||||||
|  | @ -167,6 +167,14 @@ has_action () { | ||||||
| 	sane_grep '^[^#]' "$1" >/dev/null | 	sane_grep '^[^#]' "$1" >/dev/null | ||||||
| } | } | ||||||
|  |  | ||||||
|  | is_empty_commit() { | ||||||
|  | 	tree=$(git rev-parse -q --verify "$1"^{tree} 2>/dev/null || | ||||||
|  | 		die "$1: not a commit that can be picked") | ||||||
|  | 	ptree=$(git rev-parse -q --verify "$1"^^{tree} 2>/dev/null || | ||||||
|  | 		ptree=4b825dc642cb6eb9a060e54bf8d69288fbee4904) | ||||||
|  | 	test "$tree" = "$ptree" | ||||||
|  | } | ||||||
|  |  | ||||||
| # Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and | # Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and | ||||||
| # GIT_AUTHOR_DATE exported from the current environment. | # GIT_AUTHOR_DATE exported from the current environment. | ||||||
| do_with_author () { | do_with_author () { | ||||||
|  | @ -191,12 +199,19 @@ git_sequence_editor () { | ||||||
|  |  | ||||||
| pick_one () { | pick_one () { | ||||||
| 	ff=--ff | 	ff=--ff | ||||||
|  |  | ||||||
| 	case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac | 	case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac | ||||||
| 	case "$force_rebase" in '') ;; ?*) ff= ;; esac | 	case "$force_rebase" in '') ;; ?*) ff= ;; esac | ||||||
| 	output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" | 	output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" | ||||||
|  |  | ||||||
|  | 	if is_empty_commit "$sha1" | ||||||
|  | 	then | ||||||
|  | 		empty_args="--allow-empty" | ||||||
|  | 	fi | ||||||
|  |  | ||||||
| 	test -d "$rewritten" && | 	test -d "$rewritten" && | ||||||
| 		pick_one_preserving_merges "$@" && return | 		pick_one_preserving_merges "$@" && return | ||||||
| 	output git cherry-pick $ff "$@" | 	output git cherry-pick $empty_args $ff "$@" | ||||||
| } | } | ||||||
|  |  | ||||||
| pick_one_preserving_merges () { | pick_one_preserving_merges () { | ||||||
|  | @ -780,9 +795,17 @@ git rev-list $merges_option --pretty=oneline --abbrev-commit \ | ||||||
| 	sed -n "s/^>//p" | | 	sed -n "s/^>//p" | | ||||||
| while read -r shortsha1 rest | while read -r shortsha1 rest | ||||||
| do | do | ||||||
|  |  | ||||||
|  | 	if test -z "$keep_empty" && is_empty_commit $shortsha1 | ||||||
|  | 	then | ||||||
|  | 		comment_out="# " | ||||||
|  | 	else | ||||||
|  | 		comment_out= | ||||||
|  | 	fi | ||||||
|  |  | ||||||
| 	if test t != "$preserve_merges" | 	if test t != "$preserve_merges" | ||||||
| 	then | 	then | ||||||
| 		printf '%s\n' "pick $shortsha1 $rest" >> "$todo" | 		printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo" | ||||||
| 	else | 	else | ||||||
| 		sha1=$(git rev-parse $shortsha1) | 		sha1=$(git rev-parse $shortsha1) | ||||||
| 		if test -z "$rebase_root" | 		if test -z "$rebase_root" | ||||||
|  | @ -801,7 +824,7 @@ do | ||||||
| 		if test f = "$preserve" | 		if test f = "$preserve" | ||||||
| 		then | 		then | ||||||
| 			touch "$rewritten"/$sha1 | 			touch "$rewritten"/$sha1 | ||||||
| 			printf '%s\n' "pick $shortsha1 $rest" >> "$todo" | 			printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo" | ||||||
| 		fi | 		fi | ||||||
| 	fi | 	fi | ||||||
| done | done | ||||||
|  | @ -851,6 +874,12 @@ cat >> "$todo" << EOF | ||||||
| # | # | ||||||
| EOF | EOF | ||||||
|  |  | ||||||
|  | if test -z "$keep_empty" | ||||||
|  | then | ||||||
|  | 	echo "# Note that empty commits are commented out" >>"$todo" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  |  | ||||||
| has_action "$todo" || | has_action "$todo" || | ||||||
| 	die_abort "Nothing to do" | 	die_abort "Nothing to do" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -43,6 +43,7 @@ s,strategy=!       use the given merge strategy | ||||||
| no-ff!             cherry-pick all commits, even if unchanged | no-ff!             cherry-pick all commits, even if unchanged | ||||||
| m,merge!           use merging strategies to rebase | m,merge!           use merging strategies to rebase | ||||||
| i,interactive!     let the user edit the list of commits to rebase | i,interactive!     let the user edit the list of commits to rebase | ||||||
|  | k,keep-empty	   preserve empty commits during rebase | ||||||
| f,force-rebase!    force rebase even if branch is up to date | f,force-rebase!    force rebase even if branch is up to date | ||||||
| X,strategy-option=! pass the argument through to the merge strategy | X,strategy-option=! pass the argument through to the merge strategy | ||||||
| stat!              display a diffstat of what changed upstream | stat!              display a diffstat of what changed upstream | ||||||
|  | @ -97,6 +98,7 @@ state_dir= | ||||||
| action= | action= | ||||||
| preserve_merges= | preserve_merges= | ||||||
| autosquash= | autosquash= | ||||||
|  | keep_empty= | ||||||
| test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t | test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t | ||||||
|  |  | ||||||
| read_basic_state () { | read_basic_state () { | ||||||
|  | @ -220,6 +222,9 @@ do | ||||||
| 	-i) | 	-i) | ||||||
| 		interactive_rebase=explicit | 		interactive_rebase=explicit | ||||||
| 		;; | 		;; | ||||||
|  | 	-k) | ||||||
|  | 		keep_empty=yes | ||||||
|  | 		;; | ||||||
| 	-p) | 	-p) | ||||||
| 		preserve_merges=t | 		preserve_merges=t | ||||||
| 		test -z "$interactive_rebase" && interactive_rebase=implied | 		test -z "$interactive_rebase" && interactive_rebase=implied | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Neil Horman
						Neil Horman