git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Stephan Beyer <s-beyer@gmx.net>
To: git@vger.kernel.org
Cc: Paolo Bonzini <bonzini@gnu.org>,
	Junio C Hamano <gitster@pobox.com>,
	Stephan Beyer <s-beyer@gmx.net>
Subject: [RFC/PATCH] Add git-squash tool and tests
Date: Mon,  9 Jun 2008 22:29:58 +0200	[thread overview]
Message-ID: <1213043398-30524-1-git-send-email-s-beyer@gmx.net> (raw)
In-Reply-To: <484D47C9.9050509@gnu.org>

git-squash is a simple command that, given the parent commit of X,
squashes the commits X..HEAD into one.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
Hi,

perhaps this is a little surprising, but because of:
> This could be done by providing a stand-alone git-squash command;
I thought it could be right to quickly write this as a script.

Here it is as RFC, yet without documentation.

Junio, this could be a backend for the zucchini instruction, by just
 zucchini <n>  =>  git-squash "HEAD~$(expr $n + 1)"   ;-)

 Makefile          |    1 +
 command-list.txt  |    1 +
 git-squash.sh     |   77 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 t/t3150-squash.sh |   66 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 145 insertions(+), 0 deletions(-)
 create mode 100755 git-squash.sh
 create mode 100755 t/t3150-squash.sh

diff --git a/Makefile b/Makefile
index 1937507..863004b 100644
--- a/Makefile
+++ b/Makefile
@@ -251,6 +251,7 @@ SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-sh-setup.sh
+SCRIPT_SH += git-squash.sh
 SCRIPT_SH += git-stash.sh
 SCRIPT_SH += git-submodule.sh
 SCRIPT_SH += git-web--browse.sh
diff --git a/command-list.txt b/command-list.txt
index 3583a33..e342da3 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -108,6 +108,7 @@ git-show-branch                         ancillaryinterrogators
 git-show-index                          plumbinginterrogators
 git-show-ref                            plumbinginterrogators
 git-sh-setup                            purehelpers
+git-squash                              mainporcelain
 git-stash                               mainporcelain
 git-status                              mainporcelain common
 git-stripspace                          purehelpers
diff --git a/git-squash.sh b/git-squash.sh
new file mode 100755
index 0000000..64b5949
--- /dev/null
+++ b/git-squash.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+#
+# Squash commits from HEAD up to ... into one commit.
+
+SUBDIRECTORY_OK=Yes
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git-squash [options] <commit-ish>
+--
+author=           use author <author>
+C,reuse-message=  use commit data from <commit-ish>
+F,file=           use commit message in <file>
+m,message=        use commit message <msg>
+e,edit            force edit of commit message
+s,signoff         add Signed-off-by:
+include-merges    don't fail if merge is in between
+"
+
+. git-sh-setup
+require_work_tree
+
+# test if working tree is clean
+git rev-parse --verify HEAD >/dev/null &&
+git update-index --refresh &&
+git diff-files --quiet &&
+git diff-index --cached --quiet HEAD -- ||
+	die "Working tree is dirty"
+
+git var GIT_COMMITTER_IDENT >/dev/null ||
+	die "You need to set your committer info first"
+
+HEAD=$(git rev-parse --verify HEAD) ||
+	die "No HEAD?"
+
+commitstr="git commit "
+merges=
+while test $# -gt 1
+do
+	case "$1" in
+	-m|-F|-C|--author)
+		commitstr="$commitstr $1 '$2'"
+		shift
+		;;
+	-e|-s)
+		commitstr="$commitstr $1"
+		;;
+	--include-merges)
+		merges=y
+		;;
+	--)
+		break
+		;;
+	esac
+	shift
+done
+
+test $# -gt 2 &&
+	die "Wrong number of arguments."
+test $# -lt 2 &&
+	die "No commit given."
+shift
+
+commit="$1"
+git rev-parse --verify "$commit" >/dev/null ||
+	die "$commit is no valid commit."
+
+# check for merges if no --include-merges given
+test -z "$merges" &&
+git log "$commit.." | grep -q "^Merge:" &&
+	die "$commit..HEAD contains a merge commit. You may try --include-merges."
+
+# reset and commit
+git reset --soft "$commit"
+eval "$commitstr" || {
+	git reset --hard $HEAD
+	die "Commit failed"
+}
diff --git a/t/t3150-squash.sh b/t/t3150-squash.sh
new file mode 100755
index 0000000..9f18995
--- /dev/null
+++ b/t/t3150-squash.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+test_description='git-squash'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	: >file1 &&
+	: >file2 &&
+	: >file3 &&
+	: >file4 &&
+	: >file5 &&
+	: >file6 &&
+	git add file1 &&
+	git commit -m file1 &&
+	git add file2 &&
+	git commit -m file2 &&
+	git checkout -b master2 HEAD^ &&
+	git add file3 &&
+	git commit -m file3 &&
+	git checkout master &&
+	git merge master2 &&
+	git add file4 &&
+	git commit -m file4 &&
+	git add file5 &&
+	git commit -m file5 &&
+	git add file6 &&
+	git commit -m file6
+'
+
+test_expect_success 'git-squash HEAD^ is a nop and fails' '
+	git checkout -b first master &&
+	! git squash HEAD^ &&
+	test "$(git rev-parse HEAD)" = "$(git rev-parse first)" &&
+	test "$(git rev-parse master)" = "$(git rev-parse first)"
+'
+
+test_expect_success 'git-squash works' '
+	git checkout -b second master &&
+	git squash -m "file5 and file6" --signoff HEAD^^ &&
+	test "$(git rev-parse HEAD)" = "$(git rev-parse second)" &&
+	test -f file1 -a -f file2 -a -f file3 -a \
+	     -f file4 -a -f file5 -a -f file6
+'
+
+test_expect_success 'git-squash fails if merge in between' '
+	git checkout -b third master &&
+	! git squash -C master master2^ &&
+	test "$(git rev-parse HEAD)" = "$(git rev-parse third)" &&
+	test "$(git rev-parse master)" = "$(git rev-parse third)"
+'
+
+test_expect_success 'git-squash works with --include-merges if merge in between' '
+	git checkout -b fourth master &&
+	git squash -C master --include-merges master2^ &&
+	test "$(git rev-parse HEAD)" = "$(git rev-parse fourth)"
+'
+
+test_expect_success 'git-squash aborts correctly if no commit message given' '
+	git checkout -b fifth master &&
+	! git squash HEAD~2 &&
+	test "$(git rev-parse HEAD)" = "$(git rev-parse fifth)" &&
+	test "$(git rev-parse master)" = "$(git rev-parse fifth)"
+'
+
+test_done
-- 
1.5.5.3

  parent reply	other threads:[~2008-06-09 20:31 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-06-07 22:01 [RFC] git-sequencer.txt Stephan Beyer
2008-06-09 11:45 ` squashing patches (was: Re: [RFC] git-sequencer.txt) Stephan Beyer
2008-06-09 14:04   ` Johannes Schindelin
2008-06-09 15:10   ` squashing patches Paolo Bonzini
2008-06-09 15:43     ` Paolo Bonzini
2008-06-09 16:29     ` Stephan Beyer
2008-06-09 16:37       ` Paolo Bonzini
2008-06-09 20:29     ` Stephan Beyer [this message]
2008-06-09 20:34       ` [RFC/PATCH] Add git-squash tool and tests Johannes Schindelin
2008-06-09 20:53         ` Paolo Bonzini
2008-06-09 21:34           ` Johannes Schindelin
2008-06-09 23:42             ` Stephan Beyer
2008-06-10  0:26               ` Johannes Schindelin
2008-06-09 23:46         ` Stephan Beyer
2008-06-09 19:34   ` squashing patches Junio C Hamano
2008-06-09 20:43     ` Stephan Beyer
2008-06-09 20:53       ` Jeff King
2008-06-09 23:57         ` Stephan Beyer
2008-06-10  1:00           ` Jeff King
2008-06-09 21:02       ` Junio C Hamano
2008-06-10  0:38         ` Stephan Beyer
2008-06-09 16:49 ` [RFC] git-sequencer.txt Jakub Narebski
2008-06-10  1:21   ` Stephan Beyer
2008-06-10  4:46     ` Christian Couder
2008-06-10  8:59       ` Stephan Beyer
2008-06-11  4:10         ` Christian Couder
2008-06-11 17:07       ` Daniel Barkalow
2008-06-10  6:17     ` Jakub Narebski
2008-06-12  0:22 ` [RFCv2/FYI] git-sequencer.txt Stephan Beyer
2008-06-12  1:31   ` Paolo Bonzini
2008-06-12 15:29     ` Stephan Beyer
2008-06-12 15:38       ` [RFC/PATCH] git-commit: Change --reuse-message to --reuse-commit Stephan Beyer
2008-06-12 15:56       ` [RFCv2/FYI] git-sequencer.txt Paolo Bonzini
2008-06-12  5:16   ` Junio C Hamano
2008-06-12 17:07     ` Stephan Beyer
2008-06-13  5:04       ` Paolo Bonzini
2008-06-13 12:16         ` Stephan Beyer
2008-06-13 14:42           ` Paolo Bonzini
2008-06-13 19:24       ` Olivier Marin
2008-06-12 14:10   ` Jakub Narebski
2008-06-12 17:20     ` Stephan Beyer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1213043398-30524-1-git-send-email-s-beyer@gmx.net \
    --to=s-beyer@gmx.net \
    --cc=bonzini@gnu.org \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).