mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
![Junio C Hamano](/assets/img/avatar_default.png)
Some people tend to do many little commits on a topic branch, recording all the trials and errors, and when the topic is reasonably cooked well, would want to record the net effect of the series as one commit on top of the mainline, removing the cruft from the history. The topic is then abandoned or forked off again from that point at the mainline. The barebone porcelainish that comes with core git tools does not officially support such operation, but you can fake it by using "git pull --no-merge" when such a topic branch is not a strict superset of the mainline, like this: git checkout mainline git pull --no-commit . that-topic-branch : fix conflicts if any rm -f .git/MERGE_HEAD git commit -a -m 'consolidated commit log message' git branch -f that-topic-branch ;# now fully merged This however does not work when the topic branch is a fast forward of the mainline, because normal "git pull" will never create a merge commit in such a case, and there is nothing special --no-commit could do to begin with. This patch introduces a new option, --squash, to support such a workflow officially in both fast-forward case and true merge case. The user-level operation would be the same in both cases: git checkout mainline git pull --squash . that-topic-branch : fix conflicts if any -- naturally, there would be : no conflict if fast forward. git commit -a -m 'consolidated commit log message' git branch -f that-topic-branch ;# now fully merged When the current branch is already up-to-date with respect to the other branch, there truly is nothing to do, so the new option does not have any effect. This was brought up in #git IRC channel recently. Signed-off-by: Junio C Hamano <junkio@cox.net>
65 lines
1.4 KiB
Bash
Executable file
65 lines
1.4 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
USAGE='[--mixed | --soft | --hard] [<commit-ish>]'
|
|
. git-sh-setup
|
|
|
|
tmp=${GIT_DIR}/reset.$$
|
|
trap 'rm -f $tmp-*' 0 1 2 3 15
|
|
|
|
update=
|
|
reset_type=--mixed
|
|
case "$1" in
|
|
--mixed | --soft | --hard)
|
|
reset_type="$1"
|
|
shift
|
|
;;
|
|
-*)
|
|
usage ;;
|
|
esac
|
|
|
|
rev=$(git-rev-parse --verify --default HEAD "$@") || exit
|
|
rev=$(git-rev-parse --verify $rev^0) || exit
|
|
|
|
# We need to remember the set of paths that _could_ be left
|
|
# behind before a hard reset, so that we can remove them.
|
|
if test "$reset_type" = "--hard"
|
|
then
|
|
update=-u
|
|
fi
|
|
|
|
# Soft reset does not touch the index file nor the working tree
|
|
# at all, but requires them in a good order. Other resets reset
|
|
# the index file to the tree object we are switching to.
|
|
if test "$reset_type" = "--soft"
|
|
then
|
|
if test -f "$GIT_DIR/MERGE_HEAD" ||
|
|
test "" != "$(git-ls-files --unmerged)"
|
|
then
|
|
die "Cannot do a soft reset in the middle of a merge."
|
|
fi
|
|
else
|
|
git-read-tree --reset $update "$rev" || exit
|
|
fi
|
|
|
|
# Any resets update HEAD to the head being switched to.
|
|
if orig=$(git-rev-parse --verify HEAD 2>/dev/null)
|
|
then
|
|
echo "$orig" >"$GIT_DIR/ORIG_HEAD"
|
|
else
|
|
rm -f "$GIT_DIR/ORIG_HEAD"
|
|
fi
|
|
git-update-ref -m "reset $reset_type $@" HEAD "$rev"
|
|
|
|
case "$reset_type" in
|
|
--hard )
|
|
;; # Nothing else to do
|
|
--soft )
|
|
;; # Nothing else to do
|
|
--mixed )
|
|
# Report what has not been updated.
|
|
git-update-index --refresh
|
|
;;
|
|
esac
|
|
|
|
rm -f "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/rr-cache/MERGE_RR" "$GIT_DIR/SQUASH_MSG"
|