提交 dc5d08df 编写于 作者: V Vincent Driessen

Merge branch 'release/0.4'

......@@ -7,5 +7,8 @@ Authors are (ordered by first commit date):
- Randy Merrill
- Rick Osborne
- Mark Derricutt
- Nowell Strite
- Felipe Talavera
- Guillaume-Jean Herbiet
Portions derived from other open source works are clearly marked.
0.4:
---
Release date: **2010/10/18**
* The flag parsing issues of git-flow subcommands are solved for most
platforms.
* `git flow {feature,hotfix,release} finish` now takes a `-k` flag, to keep the
branch around after finishing.
* `git flow release finish` takes a `-n` flag, to skip tagging.
* For consistency, `git flow {release,hotfix}` now, too, have a `publish` and
`track` subcommand, just like `feature`.
* Various minor fixes.
0.3:
----
Release date: **2010/07/22**
......
......@@ -12,6 +12,15 @@ git-flow installer, which can be run using the following command:
$ wget -q -O - http://github.com/nvie/gitflow/raw/develop/contrib/gitflow-installer.sh | sudo sh
For __OSX__ users, the `wget` command isn't available by default, but `curl` is, so you can run:
$ curl http://github.com/nvie/gitflow/raw/develop/contrib/gitflow-installer.sh | sudo sh
For __Windows__ users who wish to use the automated install, it is suggested that you install [Cygwin](http://www.cygwin.com/)
first to install tools like sh and wget. Then simply follow the command:
c:\Users\<user> wget -q -O - http://github.com/nvie/gitflow/raw/develop/contrib/gitflow-installer.sh | sh
If you prefer a manual installation, please use the following instructions.
After downloading the sources from Github, also fetch the submodules:
......@@ -30,20 +39,91 @@ where git-flow will be installed, simply specify it explicitly, using:
Or simply point your `PATH` environment variable to your git-flow checkout
directory.
*Installation note:*
git-flow depends on the availability of the command line utility `getopt`,
which may not be available in your Unix/Linux environment. Please use your
favorite package manager to install `getopt`. For Cygwin, install the
`util-linux` package to get `getopt`. If you use `apt-get` as your install
manager, the package name is `opt`.
Integration with your shell
---------------------------
For those who use the [Bash](http://www.gnu.org/software/bash/) shell, please
check out the excellent work on the
For those who use the [Bash](http://www.gnu.org/software/bash/) or
[ZSH](http://www.zsh.org) shell, please check out the excellent work on the
[git-flow-completion](http://github.com/bobthecow/git-flow-completion) project
by [bobthecow](http://github.com/bobthecow). It offers tab-completion for all
git-flow subcommands and branch names.
If you are a [zsh](http://www.zsh.org) user with some plugin-writing
experience, please help us develop a
[completion plugin](http://github.com/bobthecow/git-flow-completion/issues#issue/1)
for zsh, too. Please contact me on [Github](http://github.com/inbox/new/nvie)
or [Twitter](http://twitter.com/nvie) to discuss details.
For Windows users, [msysgit](http://code.google.com/p/msysgit/) is a good
starting place for installing git.
FAQ
---
* **Can I still do manual branches and merges when I use git-flow?**
Of course you can. `git-flow` does not forbid you to keep using vanilla Git
commands!
So if you want to merge `master` into `develop` for whatever reason you want
to, you can safely do so without breaking `git-flow` compatibility. Do you
want to manually merge a feature branch X into another feature branch Y? Not
a problem. As long as you do it conciously and realize what this means for
finishing those branches later on.
* **Why does git-describe not work for me?**
When finishing release and hotfix branches, that branch's HEAD is first
merged into `master` and then into `develop`. It is not the resulting new
merge commit from `master` that is merged back into `develop`. This means
that a linear path from the new `develop` branch to the new `master` commit
is not created. Even worse, a linear path is created from the new `develop`
branch to the *previous* `master` commit. Although unintended, this is
simply an effect of using the current branching rules.
When using `git-describe` in these cases, you can get very confusing and
misleading results, since `git-describe` scans the current commits linear
history for the most recent tag it finds, which will always be the *previous*
tag.
I will change this behaviour in the next version of the branching model
explicitly and I will include this behavioural change in the first version of
the Python rewrite.
For more references to this problem, see:
- Issue [#49](http://github.com/nvie/gitflow/issues/49)
- These
[two](http://groups.google.com/group/gitflow-users/browse\_thread/thread/9920a7df3d1c4908/0bb18a0bf7275ad6#0bb18a0bf7275ad6)
[discussions](http://groups.google.com/group/gitflow-users/browse\_thread/thread/19efac724bb6418a)
on the [git-flow-users](http://groups.google.com/group/gitflow-users)
mailinglist.
* **I'm getting errors when I use flags with git-flow!**
`git-flow` uses the [shFlags](http://code.google.com/p/shflags/) library to
provide platform independent flag parsing (using wichever low-level flag
parsing libraries like `getopt` or `getopts` are available). However,
`shFlags` does not work too well on a few platforms that haven't been tested
originally. This results in errors like this:
flags:WARN getopt: option invalide -- 'f' -- 'init' flags:FATAL unable to parse provided options with getopt
The platforms that suffer these errors include:
- Gentoo
- Ubuntu
- Redhat Enterprise Linux
There are open issues related to this:
[#28](http://github.com/nvie/gitflow/issues/28) and
[#39](http://github.com/nvie/gitflow/issues/39). Unfortunately, there is no
simple fix for it and all hope is placed on the Python rewrite of `git-flow`,
see issue [#33](http://github.com/nvie/gitflow/issues/33).
* **Can I use it with Windows?**
There have been reports of Windows users using `git-flow`.
<del>Un</del>fortunately, I have no Windows environment to test it on, but
this [issue](http://github.com/nvie/gitflow/issues/issue/25) should be
helpful in setting it up.
Please help out
......@@ -57,7 +137,7 @@ Feel free to fork this repo and to commit your additions. For a list of all
contributors, please see the [AUTHORS](AUTHORS) file.
Any questions, tips, or general discussion can be posted to our Google group:
http://groups.google.com/group/gitflow-users
[http://groups.google.com/group/gitflow-users](http://groups.google.com/group/gitflow-users)
License terms
......@@ -71,6 +151,11 @@ in a Github fork, of course.
Typical usage:
--------------
For the best introduction to get started to `git flow`, please read Jeff
Kreeftmeijer's blog post:
[http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/](http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/)
### Initialization
......@@ -117,3 +202,17 @@ those questions to accept the (sane) default suggestions.
For support branches, the `<base>` arg must be a commit on `master`.
Showing your appreciation
=========================
A few people already requested it, so now it's here: a Flattr button.
Of course, the best way to show your appreciation for the original
[blog post](http://nvie.com/git-model) or the git-flow tool itself remains
contributing to the community. If you'd like to show your appreciation in
another way, however, consider Flattr'ing me:
[![Flattr this][2]][1]
[1]: http://flattr.com/thing/53771/git-flow
[2]: http://api.flattr.com/button/button-static-50x60.png
......@@ -67,6 +67,11 @@ main() {
# load common functionality
. "$GITFLOW_DIR/gitflow-common"
# This environmental variable fixes non-POSIX getopt style argument
# parsing, effectively breaking git-flow subcommand parsing on several
# Linux platforms.
export POSIXLY_CORRECT=1
# use the shFlags project to parse the command line arguments
. "$GITFLOW_DIR/gitflow-shFlags"
FLAGS_PARENT="git flow"
......
......@@ -44,7 +44,7 @@ PREFIX=$(git config --get gitflow.prefix.feature)
usage() {
echo "usage: git flow feature [list] [-v]"
echo " git flow feature start [-F] <name> [<base>]"
echo " git flow feature finish [-rF] <name|nameprefix>"
echo " git flow feature finish [-rFk] <name|nameprefix>"
echo " git flow feature publish <name>"
echo " git flow feature track <name>"
echo " git flow feature diff [<name|nameprefix>]"
......@@ -74,7 +74,7 @@ cmd_list() {
warn ""
exit 0
fi
current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$feature_branches" | sed "s ^$PREFIX g")
# determine column width first
......@@ -180,7 +180,7 @@ parse_args() {
parse_cmdline "$@"
# read arguments into global variables
NAME=$1
NAME=$(last_arg "$@")
BRANCH=$PREFIX$NAME
}
......@@ -231,7 +231,8 @@ cmd_start() {
cmd_finish() {
DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F
DEFINE_boolean rebase false 'rebase instead of merge' r
DEFINE_boolean rebase false "rebase instead of merge" r
DEFINE_boolean keep false "keep branch after performing finish" k
parse_args "$@"
expand_nameprefix_arg
......@@ -343,13 +344,21 @@ helper_finish_cleanup() {
if flag fetch; then
git push "$ORIGIN" ":refs/heads/$BRANCH"
fi
git branch -D "$BRANCH"
if noflag keep; then
git branch -d "$BRANCH"
fi
echo
echo "Summary of actions:"
echo "- The feature branch '$BRANCH' was merged into '$DEVELOP_BRANCH'"
#echo "- Merge conflicts were resolved" # TODO: Add this line when it's supported
echo "- Feature branch '$BRANCH' has been removed"
if flag keep; then
echo "- Feature branch '$BRANCH' is still available"
else
echo "- Feature branch '$BRANCH' has been removed"
fi
echo "- You are now on branch '$DEVELOP_BRANCH'"
echo
}
......
......@@ -39,13 +39,13 @@
require_git_repo
require_gitflow_initialized
gitflow_load_settings
VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`")
PREFIX=$(git config --get gitflow.prefix.hotfix)
usage() {
echo "usage: git flow hotfix [list] [-v]"
echo " git flow hotfix start [-F] <version> [<base>]"
echo " git flow hotfix finish [-Fsump] <version>"
echo " git flow hotfix finish [-Fsumpk] <version>"
}
cmd_default() {
......@@ -69,7 +69,7 @@ cmd_list() {
warn ""
exit 0
fi
current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$hotfix_branches" | sed "s ^$PREFIX g")
# determine column width first
......@@ -124,7 +124,7 @@ parse_args() {
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
VERSION=$1
VERSION=$(last_arg "$@")
BRANCH=$PREFIX$VERSION
}
......@@ -137,7 +137,7 @@ require_version_arg() {
}
require_base_is_on_master() {
if ! git branch --contains "$BASE" 2>/dev/null \
if ! git branch --no-color --contains "$BASE" 2>/dev/null \
| sed 's/[* ] //g' \
| grep -q "^$MASTER_BRANCH\$"; then
die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
......@@ -194,6 +194,8 @@ cmd_finish() {
DEFINE_string signingkey "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string message "" "use the given tag message" m
DEFINE_boolean push false "push to $ORIGIN after performing finish" p
DEFINE_boolean keep false "keep branch after performing finish" k
DEFINE_boolean notag false "don't tag this release" n
parse_args "$@"
require_version_arg
......@@ -229,17 +231,19 @@ cmd_finish() {
# TODO: What do we do now?
fi
# try to tag the release
# in case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
local tagname=$VERSION_PREFIX$VERSION
if ! git_tag_exists "$tagname"; then
local opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
[ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
git tag $opts "$VERSION_PREFIX$VERSION" || \
die "Tagging failed. Please run finish again to retry."
if noflag notag; then
# try to tag the release
# in case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
local tagname=$VERSION_PREFIX$VERSION
if ! git_tag_exists "$tagname"; then
local opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
[ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
git tag $opts "$VERSION_PREFIX$VERSION" || \
die "Tagging failed. Please run finish again to retry."
fi
fi
# try to merge into develop
......@@ -257,24 +261,34 @@ cmd_finish() {
fi
# delete branch
git branch -d "$BRANCH"
if noflag keep; then
git branch -d "$BRANCH"
fi
if flag push; then
git push "$ORIGIN" "$DEVELOP_BRANCH" || \
die "Could not push to $DEVELOP_BRANCH from $ORIGIN."
git push "$ORIGIN" "$MASTER_BRANCH" || \
die "Could not push to $MASTER_BRANCH from $ORIGIN."
git push --tags "$ORIGIN" || \
die "Could not push tags to $ORIGIN."
if noflag notag; then
git push --tags "$ORIGIN" || \
die "Could not push tags to $ORIGIN."
fi
fi
echo
echo "Summary of actions:"
echo "- Latest objects have been fetched from '$ORIGIN'"
echo "- Hotfix branch has been merged into '$MASTER_BRANCH'"
echo "- The hotfix was tagged '$VERSION_PREFIX$VERSION'"
if noflag notag; then
echo "- The hotfix was tagged '$VERSION_PREFIX$VERSION'"
fi
echo "- Hotfix branch has been back-merged into '$DEVELOP_BRANCH'"
echo "- Hotfix branch '$BRANCH' has been deleted"
if flag keep; then
echo "- Hotfix branch '$BRANCH' is still available"
else
echo "- Hotfix branch '$BRANCH' has been deleted"
fi
if flag push; then
echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
fi
......
......@@ -39,13 +39,15 @@
require_git_repo
require_gitflow_initialized
gitflow_load_settings
VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`")
PREFIX=$(git config --get gitflow.prefix.release)
usage() {
echo "usage: git flow release [list] [-v]"
echo " git flow release start [-F] <version>"
echo " git flow release finish [-Fsump] <version>"
echo " git flow release finish [-Fsumpk] <version>"
echo " git flow release publish <name>"
echo " git flow release track <name>"
}
cmd_default() {
......@@ -70,7 +72,7 @@ cmd_list() {
exit 0
fi
current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$release_branches" | sed "s ^$PREFIX g")
# determine column width first
......@@ -119,7 +121,7 @@ parse_args() {
eval set -- "${FLAGS_ARGV}"
# read arguments into global variables
VERSION=$1
VERSION=$(last_arg "$@")
BRANCH=$PREFIX$VERSION
}
......@@ -132,7 +134,7 @@ require_version_arg() {
}
require_base_is_on_develop() {
if ! git branch --contains "$BASE" 2>/dev/null \
if ! git branch --no-color --contains "$BASE" 2>/dev/null \
| sed 's/[* ] //g' \
| grep -q "^$DEVELOP_BRANCH\$"; then
die "fatal: Given base '$BASE' is not a valid commit on '$DEVELOP_BRANCH'."
......@@ -189,6 +191,8 @@ cmd_finish() {
DEFINE_string signingkey "" "use the given GPG-key for the digital signature (implies -s)" u
DEFINE_string message "" "use the given tag message" m
DEFINE_boolean push false "push to $ORIGIN after performing finish" p
DEFINE_boolean keep false "keep branch after performing finish" k
DEFINE_boolean notag false "don't tag this release" n
parse_args "$@"
require_version_arg
......@@ -225,17 +229,19 @@ cmd_finish() {
# TODO: What do we do now?
fi
# try to tag the release
# in case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
local tagname=$VERSION_PREFIX$VERSION
if ! git_tag_exists "$tagname"; then
local opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
[ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
git tag $opts "$tagname" || \
die "Tagging failed. Please run finish again to retry."
if noflag notag; then
# try to tag the release
# in case a previous attempt to finish this release branch has failed,
# but the tag was set successful, we skip it now
local tagname=$VERSION_PREFIX$VERSION
if ! git_tag_exists "$tagname"; then
local opts="-a"
flag sign && opts="$opts -s"
[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
[ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'"
git tag $opts "$tagname" || \
die "Tagging failed. Please run finish again to retry."
fi
fi
# try to merge into develop
......@@ -253,26 +259,89 @@ cmd_finish() {
fi
# delete branch
git branch -d "$BRANCH"
if noflag keep; then
if [ "$BRANCH" = "$(git_current_branch)" ]; then
git checkout "$MASTER_BRANCH"
fi
git branch -d "$BRANCH"
fi
if flag push; then
git push "$ORIGIN" "$DEVELOP_BRANCH" || \
die "Could not push to $DEVELOP_BRANCH from $ORIGIN."
git push "$ORIGIN" "$MASTER_BRANCH" || \
die "Could not push to $MASTER_BRANCH from $ORIGIN."
git push --tags "$ORIGIN" || \
die "Could not push tags to $ORIGIN."
if noflag notag; then
git push --tags "$ORIGIN" || \
die "Could not push tags to $ORIGIN."
fi
git push "$ORIGIN" :"$BRANCH" || \
die "Could not delete the remote $BRANCH in $ORIGIN."
fi
echo
echo "Summary of actions:"
echo "- Latest objects have been fetched from '$ORIGIN'"
echo "- Release branch has been merged into '$MASTER_BRANCH'"
echo "- The release was tagged '$tagname'"
if noflag notag; then
echo "- The release was tagged '$tagname'"
fi
echo "- Release branch has been back-merged into '$DEVELOP_BRANCH'"
echo "- Release branch '$BRANCH' has been deleted"
if flag keep; then
echo "- Release branch '$BRANCH' is still available"
else
echo "- Release branch '$BRANCH' has been deleted"
fi
if flag push; then
echo "- '$DEVELOP_BRANCH', '$MASTER_BRANCH' and tags have been pushed to '$ORIGIN'"
echo "- Release branch '$BRANCH' in '$ORIGIN' has been deleted."
fi
echo
}
cmd_publish() {
parse_args "$@"
require_version_arg
# sanity checks
require_clean_working_tree
require_branch "$BRANCH"
git fetch -q "$ORIGIN"
require_branch_absent "$ORIGIN/$BRANCH"
# create remote branch
git push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH"
git fetch -q "$ORIGIN"
# configure remote tracking
git config "branch.$BRANCH.remote" "$ORIGIN"
git config "branch.$BRANCH.merge" "refs/heads/$BRANCH"
git checkout "$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote branch '$BRANCH' was created"
echo "- The local branch '$BRANCH' was configured to track the remote branch"
echo "- You are now on branch '$BRANCH'"
echo
}
cmd_track() {
parse_args "$@"
require_version_arg
# sanity checks
require_clean_working_tree
require_branch_absent "$BRANCH"
git fetch -q "$ORIGIN"
require_branch "$ORIGIN/$BRANCH"
# create tracking branch
git checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
echo
echo "Summary of actions:"
echo "- A new remote tracking branch '$BRANCH' was created"
echo "- You are now on branch '$BRANCH'"
echo
}
......@@ -39,7 +39,7 @@
require_git_repo
require_gitflow_initialized
gitflow_load_settings
VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`")
PREFIX=$(git config --get gitflow.prefix.support)
warn "note: The support subcommand is still very EXPERIMENTAL!"
......@@ -71,7 +71,7 @@ cmd_list() {
warn ""
exit 0
fi
current_branch=$(git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
current_branch=$(git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g')
short_names=$(echo "$support_branches" | sed "s ^$PREFIX g")
# determine column width first
......@@ -148,7 +148,7 @@ require_base_arg() {
}
require_base_is_on_master() {
if ! git branch --contains "$BASE" 2>/dev/null \
if ! git branch --no-color --contains "$BASE" 2>/dev/null \
| sed 's/[* ] //g' \
| grep -q "^$MASTER_BRANCH\$"; then
die "fatal: Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."
......
......@@ -36,7 +36,7 @@
# policies, either expressed or implied, of Vincent Driessen.
#
GITFLOW_VERSION=0.3
GITFLOW_VERSION=0.4
usage() {
echo "usage: git flow version"
......
......@@ -44,6 +44,14 @@
warn() { echo "$@" >&2; }
die() { warn "$@"; exit 1; }
# argument processing
last_arg() {
if [ $# -ne 0 ]; then
shift $(expr $# - 1)
echo "$1"
fi
}
# set logic
has() {
local item=$1; shift
......@@ -66,13 +74,13 @@ noflag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -ne $FLAGS_TRUE ]; }
# Git specific common functionality
#
git_local_branches() { git branch | sed 's/^[* ] //'; }
git_remote_branches() { git branch -r | sed 's/^[* ] //'; }
git_all_branches() { ( git branch; git branch -r) | sed 's/^[* ] //'; }
git_local_branches() { git branch --no-color | sed 's/^[* ] //'; }
git_remote_branches() { git branch -r --no-color | sed 's/^[* ] //'; }
git_all_branches() { ( git branch --no-color; git branch -r --no-color) | sed 's/^[* ] //'; }
git_all_tags() { git tag; }
git_current_branch() {
git branch | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'
git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'
}
git_is_clean_working_tree() {
......@@ -140,7 +148,7 @@ git_compare_branches() {
git_is_branch_merged_into() {
local subject=$1
local base=$2
local all_merges=$(git branch --contains $subject | sed 's/^[* ] //')
local all_merges=$(git branch --no-color --contains $subject | sed 's/^[* ] //')
has $base $all_merges
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册