Skip to content

Commit

Permalink
Refactor and improve git squash
Browse files Browse the repository at this point in the history
`git squash` refactor:
- first argument can be a branch or a commit reference
- the `--me` argument is not required anymore
- use `git reset --soft` is squashing on a current branch
- if squashing on master branch, prompt for confirmation
- does not delete provided branch after squashing
- fix bug: if `git merge --squash` command fails, exit script

Update README and man pages.

Fixes #95
Closes #198
  • Loading branch information
Bruno Sutic committed Jul 20, 2014
1 parent 458c08d commit b2576ad
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 42 deletions.
11 changes: 9 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,13 +505,20 @@ $ git graft new_feature dev
$ git graft new_feature
```
## git-squash <src-branch> [msg]
## git-squash <src-branch|commit ref> [msg]
Merge commits from `src-branch` into the current branch as a _single_ commit. When `[msg]` is given `git-commit(1)` will be invoked with that message. This is useful when small individual commits within a topic branch are irrelevant and you want to consider the topic as a single change.
Merge commits from `src-branch` into the current branch as a _single_ commit.
Also works if a commit reference from the current branch is provided.
When `[msg]` is given `git-commit(1)` will be invoked with that message. This is
useful when small individual commits within a topic branch are irrelevant and
you want to consider the topic as a single change.
```bash
$ git squash fixed-cursor-styling
$ git squash fixed-cursor-styling "Fixed cursor styling"
$ git squash 95b7c52
$ git squash HEAD~3
$ git squash HEAD~3 "Work on a feature"
```
## git-changelog
Expand Down
73 changes: 44 additions & 29 deletions bin/git-squash
Original file line number Diff line number Diff line change
@@ -1,38 +1,53 @@
#!/bin/sh
#!/bin/bash

src=$1
msg=$2
src="$1"
msg="$2"

test -z $src && echo "source branch required, or use --me." && exit 1
is_branch() {
git show-ref --verify --quiet "refs/heads/$src"
}

# squash current branch
# TODO: do this in a less hacky way
# TODO: less sketchy arguments
is_commit_reference() {
git rev-parse --verify --quiet "$src" > /dev/null 2>&1
}

if [[ $1 == "--me" ]]; then
msg=$3
branch=`git rev-parse --abbrev-ref HEAD`

# merge against target branch or master
git checkout ${2-master}

git checkout -B squash-tmp
git squash $branch
git branch -D $branch
git checkout -B $branch
git branch -D squash-tmp
is_on_current_branch() {
local commit_sha=`git rev-parse "$src"`
git rev-list HEAD |
grep -q "$commit_sha"
}

commit_if_msg_provided() {
if test -n "$msg"; then
git commit -a -m "$msg"
fi

exit
fi

# squash $src

git merge --squash $src

if test -n "$msg"; then
git commit -a -m "$msg" && git branch -D $src
}

prompt_continuation_if_squashing_master() {
if [[ $src =~ ^master$ ]]; then
read -p "Warning: squashing '$src'! Continue [y/N]? " -r
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
echo "Exiting"
exit 1
fi
fi
}

squash_branch() {
prompt_continuation_if_squashing_master
git merge --squash "$src" || exit 1 # quits if `git merge` fails
commit_if_msg_provided
}

squash_current_branch() {
git reset --soft "$src" || exit 1 # quits if `git reset` fails
commit_if_msg_provided
}

if `is_branch`; then
squash_branch
elif `is_commit_reference` && `is_on_current_branch`; then
squash_current_branch
else
echo "Source branch or commit reference required." 1>&2 && exit 1
fi
17 changes: 11 additions & 6 deletions man/git-squash.1
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
.\" generated with Ronn/v0.7.3
.\" https://github.com/rtomayko/ronn/tree/0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SQUASH" "1" "July 2012" "" ""
.TH "GIT\-SQUASH" "1" "July 2014" "" ""
.
.SH "NAME"
\fBgit\-squash\fR \- Import changes from a branch
\fBgit\-squash\fR \- Import changes form a branch
.
.SH "SYNOPSIS"
\fBgit\-squash\fR <source\-branch> [<commit\-message>]
\fBgit\-squash\fR <source\-branch|commit ref> [<commit\-message>]
.
.SH "DESCRIPTION"
Produce the working tree and index state as if a real merge happened without the commit or merge marks\.
Expand All @@ -19,6 +19,9 @@ Produce the working tree and index state as if a real merge happened without the
Branch to squash on the actual branch\.
.
.P
<commit reference> A commit reference (has to be from the current branch) can also be used as the first argument\. A range of commits \fIsha\fR\.\.HEAD will be squashed\.
.
.P
<commit\-message>
.
.P
Expand All @@ -35,14 +38,16 @@ Squash commit \-\- not updating HEAD
my\-changed\-file | 1 +
1 file changed, 1 insertion(+)
$ git commit \-m "New commit without a real merge"

$ git squash HEAD~3 "Commit message"
.
.fi
.
.SH "AUTHOR"
Written by Jesús Espino <\fIjespinog@gmail\.com\fR>
.
.SH "REPORTING BUGS"
<\fIhttp://github\.com/visionmedia/git\-extras/issues\fR>
<\fIhttps://github\.com/visionmedia/git\-extras/issues\fR>
.
.SH "SEE ALSO"
<\fIhttp://github\.com/visionmedia/git\-extras\fR>
<\fIhttps://github\.com/visionmedia/git\-extras\fR>
14 changes: 10 additions & 4 deletions man/git-squash.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion man/git-squash.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ git-squash(1) -- Import changes form a branch

## SYNOPSIS

`git-squash` &lt;source-branch&gt; [&lt;commit-message&gt;]
`git-squash` &lt;source-branch|commit ref&gt; [&lt;commit-message&gt;]

## DESCRIPTION

Expand All @@ -16,6 +16,10 @@ git-squash(1) -- Import changes form a branch

Branch to squash on the actual branch.

&lt;commit reference&gt;
A commit reference (has to be from the current branch) can also be used as the
first argument. A range of commits <sha>..HEAD will be squashed.

&lt;commit-message&gt;

If commit-message is given, commit the squash result and delete the source-branch.
Expand All @@ -30,6 +34,8 @@ git-squash(1) -- Import changes form a branch
1 file changed, 1 insertion(+)
$ git commit -m "New commit without a real merge"

$ git squash HEAD~3 "Commit message"

## AUTHOR

Written by Jesús Espino &lt;<jespinog@gmail.com>&gt;
Expand Down

0 comments on commit b2576ad

Please sign in to comment.