diff --git a/AUTHORS b/AUTHORS index f7d1e6638..aded955fc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -19,5 +19,6 @@ Authors are (ordered by first commit date): - Emre Berge Ergenekon - Eric Holmes - Vedang Manerikar +- Myke Hines Portions derived from other open source works are clearly marked. diff --git a/README.mdown b/README.mdown index c7238e6f0..b720b125e 100644 --- a/README.mdown +++ b/README.mdown @@ -1,3 +1,34 @@ +> [!IMPORTANT] +> +> # ⚠️ git-flow has moved to git-flow-next! +> +> **This repository is no longer maintained.** The wonderful team at [Tower](https://www.git-tower.com/) has created [**git-flow-next**](https://git-flow.sh) — a modern, fully customizable evolution of git-flow, built on a generic branch dependency model. It’s fully backward compatible with git-flow, open source, and actively maintained. +> +> ### Get started with git-flow-next: +> +> - **Website:** https://git-flow.sh +> - **GitHub:** https://github.com/gittower/git-flow-next +> - **Evolution Story:** Read about the journey from git-flow → git-flow-avh → git-flow-next in [their blog post](https://git-flow.sh/blog) +> +> ### Why git-flow-next? +> +> git-flow-next builds upon the foundation laid by the original git-flow, offering: +> +> - Full customization of branch names and workflow +> - Modern implementation with active maintenance +> - Backward compatibility with existing git-flow workflows +> - Upcoming features like stacked branches and topic branch syncing +> +> ### Thank you ❤️ +> +> To everyone who has used, contributed to, and supported git-flow over the past 15+ years — thank you! Your feedback, contributions, and adoption made git-flow one of the most widely-used Git workflow tools. Special thanks to Peter van der Does for maintaining git-flow-avh, and to the folks at Tower for carrying the torch forward with git-flow-next. + +--- + +(Below, you’ll find the original documentation for historical reference.) + +--- + git-flow ======== @@ -40,37 +71,6 @@ See the [FAQ](http://github.com/nvie/gitflow/wiki/FAQ) section of the project Wiki. -Please help out ---------------- -This project is still under development. Feedback and suggestions are very -welcome and I encourage you to use the [Issues -list](http://github.com/nvie/gitflow/issues) on Github to provide that -feedback. - -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) - -Contributing ------------- -Fork the repository. Then, run: - - git clone --recursive git@github.com:/gitflow.git - cd gitflow - git branch master origin/master - git flow init -d - git flow feature start - -Then, do work and commit your changes. **Hint**: ``export PATH=`pwd`:$PATH`` -from within the gitflow directory makes sure you're using the version of -gitflow you're currently developing. - - git flow feature publish - -When done, open a pull request to your feature branch. - License terms ------------- git-flow is published under the liberal terms of the BSD License, see the @@ -131,18 +131,3 @@ The ``-d`` flag will accept all defaults. git flow support start For support branches, the `` 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 diff --git a/contrib/msysgit-install.cmd b/contrib/msysgit-install.cmd index 5f005bfa7..994235c79 100644 --- a/contrib/msysgit-install.cmd +++ b/contrib/msysgit-install.cmd @@ -63,6 +63,7 @@ goto :End :ChkGetopt :: %1 is getopt.exe if exist "%GIT_HOME%\bin\%1" goto :EOF +if exist "%USERPROFILE%\bin\%1" goto :EOF if exist "%~f$PATH:1" goto :EOF echo %GIT_HOME%\bin\%1 not found.>&2 echo You have to install this file manually. See the GitFlow README. diff --git a/git-flow b/git-flow index 93e9f0f73..fd16d5168 100755 --- a/git-flow +++ b/git-flow @@ -80,6 +80,11 @@ main() { # use the shFlags project to parse the command line arguments . "$GITFLOW_DIR/gitflow-shFlags" FLAGS_PARENT="git flow" + + # allow user to request git action logging + DEFINE_boolean show_commands false 'show actions taken (git commands)' g + + # do actual parsing FLAGS "$@" || exit $? eval set -- "${FLAGS_ARGV}" @@ -109,7 +114,10 @@ main() { fi # run the specified action - cmd_$SUBACTION "$@" + if [ $SUBACTION != "help" ] && [ $SUBCOMMAND != "init" ] ; then + init + fi + cmd_$SUBACTION "$@" } main "$@" diff --git a/git-flow-feature b/git-flow-feature index e97d67825..55198ad82 100644 --- a/git-flow-feature +++ b/git-flow-feature @@ -36,15 +36,17 @@ # policies, either expressed or implied, of Vincent Driessen. # -require_git_repo -require_gitflow_initialized -gitflow_load_settings -PREFIX=$(git config --get gitflow.prefix.feature) +init() { + require_git_repo + require_gitflow_initialized + gitflow_load_settings + PREFIX=$(git config --get gitflow.prefix.feature) +} usage() { echo "usage: git flow feature [list] [-v]" echo " git flow feature start [-F] []" - echo " git flow feature finish [-rFkD] []" + echo " git flow feature finish [-rFkDS] []" echo " git flow feature publish " echo " git flow feature track " echo " git flow feature diff []" @@ -202,7 +204,7 @@ cmd_start() { # update the local repo with remote changes, if asked if flag fetch; then - git fetch -q "$ORIGIN" "$DEVELOP_BRANCH" + git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" fi # if the origin branch counterpart exists, assert that the local branch @@ -212,7 +214,7 @@ cmd_start() { fi # create branch - if ! git checkout -b "$BRANCH" "$BASE"; then + if ! git_do checkout -b "$BRANCH" "$BASE"; then die "Could not create feature branch '$BRANCH'" fi @@ -232,6 +234,7 @@ cmd_finish() { DEFINE_boolean rebase false "rebase instead of merge" r DEFINE_boolean keep false "keep branch after performing finish" k DEFINE_boolean force_delete false "force delete feature branch after finish" D + DEFINE_boolean squash false "squash feature during merge" S parse_args "$@" expand_nameprefix_arg_or_current @@ -284,8 +287,8 @@ cmd_finish() { # update local repo with remote changes first, if asked if has "$ORIGIN/$BRANCH" $(git_remote_branches); then if flag fetch; then - git fetch -q "$ORIGIN" "$BRANCH" - git fetch -q "$ORIGIN" "$DEVELOP_BRANCH" + git_do fetch -q "$ORIGIN" "$BRANCH" + git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" fi fi @@ -308,11 +311,17 @@ cmd_finish() { fi # merge into BASE - git checkout "$DEVELOP_BRANCH" + git_do checkout "$DEVELOP_BRANCH" if [ "$(git rev-list -n2 "$DEVELOP_BRANCH..$BRANCH" | wc -l)" -eq 1 ]; then - git merge --ff "$BRANCH" + git_do merge --ff "$BRANCH" else - git merge --no-ff "$BRANCH" + if noflag squash; then + git_do merge --no-ff "$BRANCH" + else + git_do merge --squash "$BRANCH" + git_do commit + git_do merge "$BRANCH" + fi fi if [ $? -ne 0 ]; then @@ -342,15 +351,15 @@ helper_finish_cleanup() { # delete branch if flag fetch; then - git push "$ORIGIN" ":refs/heads/$BRANCH" + git_do push "$ORIGIN" ":refs/heads/$BRANCH" fi if noflag keep; then if flag force_delete; then - git branch -D "$BRANCH" + git_do branch -D "$BRANCH" else - git branch -d "$BRANCH" + git_do branch -d "$BRANCH" fi fi @@ -374,17 +383,17 @@ cmd_publish() { # sanity checks require_clean_working_tree require_branch "$BRANCH" - git fetch -q "$ORIGIN" + git_do fetch -q "$ORIGIN" require_branch_absent "$ORIGIN/$BRANCH" # create remote branch - git push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH" - git fetch -q "$ORIGIN" + git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH" + git_do fetch -q "$ORIGIN" # configure remote tracking - git config "branch.$BRANCH.remote" "$ORIGIN" - git config "branch.$BRANCH.merge" "refs/heads/$BRANCH" - git checkout "$BRANCH" + git_do config "branch.$BRANCH.remote" "$ORIGIN" + git_do config "branch.$BRANCH.merge" "refs/heads/$BRANCH" + git_do checkout "$BRANCH" echo echo "Summary of actions:" @@ -401,11 +410,11 @@ cmd_track() { # sanity checks require_clean_working_tree require_branch_absent "$BRANCH" - git fetch -q "$ORIGIN" + git_do fetch -q "$ORIGIN" require_branch "$ORIGIN/$BRANCH" # create tracking branch - git checkout -b "$BRANCH" "$ORIGIN/$BRANCH" + git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH" echo echo "Summary of actions:" @@ -436,7 +445,7 @@ cmd_checkout() { if [ "$NAME" != "" ]; then expand_nameprefix_arg - git checkout "$BRANCH" + git_do checkout "$BRANCH" else die "Name a feature branch explicitly." fi @@ -455,12 +464,12 @@ cmd_rebase() { require_clean_working_tree require_branch "$BRANCH" - git checkout -q "$BRANCH" + git_do checkout -q "$BRANCH" local OPTS= if flag interactive; then OPTS="$OPTS -i" fi - git rebase $OPTS "$DEVELOP_BRANCH" + git_do rebase $OPTS "$DEVELOP_BRANCH" } avoid_accidental_cross_branch_action() { @@ -502,20 +511,20 @@ cmd_pull() { # we already have a local branch called like this, so simply pull the # remote changes in if flag rebase; then - if ! git pull --rebase -q "$REMOTE" "$BRANCH"; then + if ! git_do pull --rebase -q "$REMOTE" "$BRANCH"; then warn "Pull was aborted. There might be conflicts during rebase or '$REMOTE' might be inaccessible." exit 1 fi else - it pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'." + git_do pull -q "$REMOTE" "$BRANCH" || die "Failed to pull from remote '$REMOTE'." fi echo "Pulled $REMOTE's changes into $BRANCH." else # setup the local branch clone for the first time - git fetch -q "$REMOTE" "$BRANCH" || die "Fetch failed." # stores in FETCH_HEAD - git branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed." - git checkout -q "$BRANCH" || die "Checking out new local branch failed." + git_do fetch -q "$REMOTE" "$BRANCH" || die "Fetch failed." # stores in FETCH_HEAD + git_do branch --no-track "$BRANCH" FETCH_HEAD || die "Branch failed." + git_do checkout -q "$BRANCH" || die "Checking out new local branch failed." echo "Created local branch $BRANCH based on $REMOTE's $BRANCH." fi } diff --git a/git-flow-hotfix b/git-flow-hotfix index b355f3019..ba485f6fe 100644 --- a/git-flow-hotfix +++ b/git-flow-hotfix @@ -36,17 +36,20 @@ # policies, either expressed or implied, of Vincent Driessen. # -require_git_repo -require_gitflow_initialized -gitflow_load_settings -VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`") -PREFIX=$(git config --get gitflow.prefix.hotfix) +init() { + require_git_repo + require_gitflow_initialized + gitflow_load_settings + 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] []" echo " git flow hotfix finish [-Fsumpk] " echo " git flow hotfix publish " + echo " git flow hotfix track " } cmd_default() { @@ -166,14 +169,14 @@ cmd_start() { require_branch_absent "$BRANCH" require_tag_absent "$VERSION_PREFIX$VERSION" if flag fetch; then - git fetch -q "$ORIGIN" "$MASTER_BRANCH" + git_do fetch -q "$ORIGIN" "$MASTER_BRANCH" fi if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then require_branches_equal "$MASTER_BRANCH" "$ORIGIN/$MASTER_BRANCH" fi # create branch - git checkout -b "$BRANCH" "$BASE" + git_do checkout -b "$BRANCH" "$BASE" echo echo "Summary of actions:" @@ -196,17 +199,17 @@ cmd_publish() { # sanity checks require_clean_working_tree require_branch "$BRANCH" - git fetch -q "$ORIGIN" + git_do fetch -q "$ORIGIN" require_branch_absent "$ORIGIN/$BRANCH" # create remote branch - git push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH" - git fetch -q "$ORIGIN" + git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH" + git_do fetch -q "$ORIGIN" # configure remote tracking git config "branch.$BRANCH.remote" "$ORIGIN" git config "branch.$BRANCH.merge" "refs/heads/$BRANCH" - git checkout "$BRANCH" + git_do checkout "$BRANCH" echo echo "Summary of actions:" @@ -216,11 +219,32 @@ cmd_publish() { echo } +cmd_track() { + parse_args "$@" + require_version_arg + + # sanity checks + require_clean_working_tree + require_branch_absent "$BRANCH" + git_do fetch -q "$ORIGIN" + require_branch "$ORIGIN/$BRANCH" + + # create tracking branch + git_do 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 +} + cmd_finish() { DEFINE_boolean fetch false "fetch from $ORIGIN before performing finish" F DEFINE_boolean sign false "sign the release tag cryptographically" s 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_string messagefile "" "use the contents of the given file as tag message" f 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 @@ -236,9 +260,9 @@ cmd_finish() { require_branch "$BRANCH" require_clean_working_tree if flag fetch; then - git fetch -q "$ORIGIN" "$MASTER_BRANCH" || \ + git_do fetch -q "$ORIGIN" "$MASTER_BRANCH" || \ die "Could not fetch $MASTER_BRANCH from $ORIGIN." - git fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \ + git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \ die "Could not fetch $DEVELOP_BRANCH from $ORIGIN." fi if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then @@ -252,9 +276,9 @@ cmd_finish() { # in case a previous attempt to finish this release branch has failed, # but the merge into master was successful, we skip it now if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then - git checkout "$MASTER_BRANCH" || \ + git_do checkout "$MASTER_BRANCH" || \ die "Could not check out $MASTER_BRANCH." - git merge --no-ff "$BRANCH" || \ + git_do merge --no-ff "$BRANCH" || \ die "There were merge conflicts." # TODO: What do we do now? fi @@ -269,7 +293,8 @@ cmd_finish() { flag sign && opts="$opts -s" [ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'" [ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'" - eval git tag $opts "$VERSION_PREFIX$VERSION" || \ + [ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'" + eval git_do tag $opts "$VERSION_PREFIX$VERSION" "$BRANCH" || \ die "Tagging failed. Please run finish again to retry." fi fi @@ -278,28 +303,28 @@ cmd_finish() { # in case a previous attempt to finish this release branch has failed, # but the merge into develop was successful, we skip it now if ! git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH"; then - git checkout "$DEVELOP_BRANCH" || \ + git_do checkout "$DEVELOP_BRANCH" || \ die "Could not check out $DEVELOP_BRANCH." # TODO: Actually, accounting for 'git describe' pays, so we should # ideally git merge --no-ff $tagname here, instead! - git merge --no-ff "$BRANCH" || \ + git_do merge --no-ff "$BRANCH" || \ die "There were merge conflicts." # TODO: What do we do now? fi # delete branch if noflag keep; then - git branch -d "$BRANCH" + git_do branch -d "$BRANCH" fi if flag push; then - git push "$ORIGIN" "$DEVELOP_BRANCH" || \ + git_do push "$ORIGIN" "$DEVELOP_BRANCH" || \ die "Could not push to $DEVELOP_BRANCH from $ORIGIN." - git push "$ORIGIN" "$MASTER_BRANCH" || \ + git_do push "$ORIGIN" "$MASTER_BRANCH" || \ die "Could not push to $MASTER_BRANCH from $ORIGIN." if noflag notag; then - git push --tags "$ORIGIN" || \ + git_do push --tags "$ORIGIN" || \ die "Could not push tags to $ORIGIN." fi fi diff --git a/git-flow-init b/git-flow-init index 4afa1c25e..5b4e7e807 100644 --- a/git-flow-init +++ b/git-flow-init @@ -53,7 +53,7 @@ cmd_default() { parse_args "$@" if ! git rev-parse --git-dir >/dev/null 2>&1; then - git init + git_do init else # assure that we are not working in a repo with local changes git_repo_is_headless || require_clean_working_tree @@ -121,14 +121,14 @@ cmd_default() { # name exists, checkout that branch and use it for master if ! git_local_branch_exists "$master_branch" && \ git_remote_branch_exists "origin/$master_branch"; then - git branch "$master_branch" "origin/$master_branch" >/dev/null 2>&1 + git_do branch "$master_branch" "origin/$master_branch" >/dev/null 2>&1 elif ! git_local_branch_exists "$master_branch"; then die "Local branch '$master_branch' does not exist." fi fi # store the name of the master branch - git config gitflow.branch.master "$master_branch" + git_do config gitflow.branch.master "$master_branch" fi # add a develop branch if no such branch exists yet @@ -153,11 +153,17 @@ cmd_default() { default_suggestion= for guess in $(git config --get gitflow.branch.develop) \ 'develop' 'int' 'integration' 'master'; do - if git_local_branch_exists "$guess"; then + if git_local_branch_exists "$guess" && [ "$guess" != "$master_branch" ]; then default_suggestion="$guess" break fi done + + if [ -z $default_suggestion ]; then + should_check_existence=NO + default_suggestion=$(git config --get gitflow.branch.develop || echo develop) + fi + fi printf "Branch name for \"next release\" development: [$default_suggestion] " @@ -179,7 +185,7 @@ cmd_default() { fi # store the name of the develop branch - git config gitflow.branch.develop "$develop_branch" + git_do config gitflow.branch.develop "$develop_branch" fi # Creation of HEAD @@ -188,8 +194,8 @@ cmd_default() { # it to be able to create new branches. local created_gitflow_branch=0 if ! git rev-parse --quiet --verify HEAD >/dev/null 2>&1; then - git symbolic-ref HEAD "refs/heads/$master_branch" - git commit --allow-empty --quiet -m "Initial commit" + git_do symbolic-ref HEAD "refs/heads/$master_branch" + git_do commit --allow-empty --quiet -m "Initial commit" created_gitflow_branch=1 fi @@ -207,9 +213,9 @@ cmd_default() { # the develop branch now in that case (we base it on master, of course) if ! git_local_branch_exists "$develop_branch"; then if git_remote_branch_exists "origin/$develop_branch"; then - git branch "$develop_branch" "origin/$develop_branch" >/dev/null 2>&1 + git_do branch "$develop_branch" "origin/$develop_branch" >/dev/null 2>&1 else - git branch --no-track "$develop_branch" "$master_branch" + git_do branch --no-track "$develop_branch" "$master_branch" fi created_gitflow_branch=1 fi @@ -219,7 +225,7 @@ cmd_default() { # switch to develop branch if its newly created if [ $created_gitflow_branch -eq 1 ]; then - git checkout -q "$develop_branch" + git_do checkout -q "$develop_branch" fi # finally, ask the user for naming conventions (branch and tag prefixes) @@ -245,7 +251,7 @@ cmd_default() { printf "\n" fi [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} - git config gitflow.prefix.feature "$prefix" + git_do config gitflow.prefix.feature "$prefix" fi # Release branches @@ -258,7 +264,7 @@ cmd_default() { printf "\n" fi [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} - git config gitflow.prefix.release "$prefix" + git_do config gitflow.prefix.release "$prefix" fi @@ -272,7 +278,7 @@ cmd_default() { printf "\n" fi [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} - git config gitflow.prefix.hotfix "$prefix" + git_do config gitflow.prefix.hotfix "$prefix" fi @@ -286,7 +292,7 @@ cmd_default() { printf "\n" fi [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} - git config gitflow.prefix.support "$prefix" + git_do config gitflow.prefix.support "$prefix" fi @@ -300,7 +306,7 @@ cmd_default() { printf "\n" fi [ "$answer" = "-" ] && prefix= || prefix=${answer:-$default_suggestion} - git config gitflow.prefix.versiontag "$prefix" + git_do config gitflow.prefix.versiontag "$prefix" fi diff --git a/git-flow-release b/git-flow-release index bb39d5276..cb95bd486 100644 --- a/git-flow-release +++ b/git-flow-release @@ -36,16 +36,18 @@ # policies, either expressed or implied, of Vincent Driessen. # -require_git_repo -require_gitflow_initialized -gitflow_load_settings -VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`") -PREFIX=$(git config --get gitflow.prefix.release) +init() { + require_git_repo + require_gitflow_initialized + gitflow_load_settings + 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] []" - echo " git flow release finish [-Fsumpk] " + echo " git flow release finish [-FsumpkS] " echo " git flow release publish " echo " git flow release track " } @@ -134,7 +136,7 @@ require_version_arg() { } require_base_is_on_develop() { - if ! git branch --no-color --contains "$BASE" 2>/dev/null \ + if ! git_do 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'." @@ -162,14 +164,14 @@ cmd_start() { require_branch_absent "$BRANCH" require_tag_absent "$VERSION_PREFIX$VERSION" if flag fetch; then - git fetch -q "$ORIGIN" "$DEVELOP_BRANCH" + git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" fi if has "$ORIGIN/$DEVELOP_BRANCH" $(git_remote_branches); then require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH" fi # create branch - git checkout -b "$BRANCH" "$BASE" + git_do checkout -b "$BRANCH" "$BASE" echo echo "Summary of actions:" @@ -190,9 +192,11 @@ cmd_finish() { DEFINE_boolean sign false "sign the release tag cryptographically" s 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_string messagefile "" "use the contents of the given file as a tag message" f 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 + DEFINE_boolean squash false "squash release during merge" S parse_args "$@" require_version_arg @@ -206,9 +210,9 @@ cmd_finish() { require_branch "$BRANCH" require_clean_working_tree if flag fetch; then - git fetch -q "$ORIGIN" "$MASTER_BRANCH" || \ + git_do fetch -q "$ORIGIN" "$MASTER_BRANCH" || \ die "Could not fetch $MASTER_BRANCH from $ORIGIN." - git fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \ + git_do fetch -q "$ORIGIN" "$DEVELOP_BRANCH" || \ die "Could not fetch $DEVELOP_BRANCH from $ORIGIN." fi if has "$ORIGIN/$MASTER_BRANCH" $(git_remote_branches); then @@ -222,11 +226,17 @@ cmd_finish() { # in case a previous attempt to finish this release branch has failed, # but the merge into master was successful, we skip it now if ! git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH"; then - git checkout "$MASTER_BRANCH" || \ + git_do checkout "$MASTER_BRANCH" || \ die "Could not check out $MASTER_BRANCH." - git merge --no-ff "$BRANCH" || \ - die "There were merge conflicts." - # TODO: What do we do now? + if noflag squash; then + git_do merge --no-ff "$BRANCH" || \ + die "There were merge conflicts." + # TODO: What do we do now? + else + git_do merge --squash "$BRANCH" || \ + die "There were merge conflicts." + git_do commit + fi fi if noflag notag; then @@ -239,7 +249,8 @@ cmd_finish() { flag sign && opts="$opts -s" [ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'" [ "$FLAGS_message" != "" ] && opts="$opts -m '$FLAGS_message'" - eval git tag $opts "$tagname" || \ + [ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'" + eval git_do tag $opts "$tagname" "$BRANCH" || \ die "Tagging failed. Please run finish again to retry." fi fi @@ -248,34 +259,41 @@ cmd_finish() { # in case a previous attempt to finish this release branch has failed, # but the merge into develop was successful, we skip it now if ! git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH"; then - git checkout "$DEVELOP_BRANCH" || \ + git_do checkout "$DEVELOP_BRANCH" || \ die "Could not check out $DEVELOP_BRANCH." # TODO: Actually, accounting for 'git describe' pays, so we should # ideally git merge --no-ff $tagname here, instead! - git merge --no-ff "$BRANCH" || \ - die "There were merge conflicts." - # TODO: What do we do now? + if noflag squash; then + git_do merge --no-ff "$BRANCH" || \ + die "There were merge conflicts." + # TODO: What do we do now? + else + git_do merge --squash "$BRANCH" || \ + die "There were merge conflicts." + # TODO: What do we do now? + git_do commit + fi fi # delete branch if noflag keep; then if [ "$BRANCH" = "$(git_current_branch)" ]; then - git checkout "$MASTER_BRANCH" + git_do checkout "$MASTER_BRANCH" fi - git branch -d "$BRANCH" + git_do branch -d "$BRANCH" fi if flag push; then - git push "$ORIGIN" "$DEVELOP_BRANCH" || \ + git_do push "$ORIGIN" "$DEVELOP_BRANCH" || \ die "Could not push to $DEVELOP_BRANCH from $ORIGIN." - git push "$ORIGIN" "$MASTER_BRANCH" || \ + git_do push "$ORIGIN" "$MASTER_BRANCH" || \ die "Could not push to $MASTER_BRANCH from $ORIGIN." if noflag notag; then - git push --tags "$ORIGIN" || \ + git_do push --tags "$ORIGIN" || \ die "Could not push tags to $ORIGIN." fi - git push "$ORIGIN" :"$BRANCH" || \ + git_do push "$ORIGIN" :"$BRANCH" || \ die "Could not delete the remote $BRANCH in $ORIGIN." fi @@ -306,17 +324,17 @@ cmd_publish() { # sanity checks require_clean_working_tree require_branch "$BRANCH" - git fetch -q "$ORIGIN" + git_do fetch -q "$ORIGIN" require_branch_absent "$ORIGIN/$BRANCH" # create remote branch - git push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH" - git fetch -q "$ORIGIN" + git_do push "$ORIGIN" "$BRANCH:refs/heads/$BRANCH" + git_do fetch -q "$ORIGIN" # configure remote tracking - git config "branch.$BRANCH.remote" "$ORIGIN" - git config "branch.$BRANCH.merge" "refs/heads/$BRANCH" - git checkout "$BRANCH" + git_do config "branch.$BRANCH.remote" "$ORIGIN" + git_do config "branch.$BRANCH.merge" "refs/heads/$BRANCH" + git_do checkout "$BRANCH" echo echo "Summary of actions:" @@ -333,11 +351,11 @@ cmd_track() { # sanity checks require_clean_working_tree require_branch_absent "$BRANCH" - git fetch -q "$ORIGIN" + git_do fetch -q "$ORIGIN" require_branch "$ORIGIN/$BRANCH" # create tracking branch - git checkout -b "$BRANCH" "$ORIGIN/$BRANCH" + git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH" echo echo "Summary of actions:" diff --git a/git-flow-support b/git-flow-support index 605694dc9..cdbfc717c 100644 --- a/git-flow-support +++ b/git-flow-support @@ -36,11 +36,13 @@ # policies, either expressed or implied, of Vincent Driessen. # -require_git_repo -require_gitflow_initialized -gitflow_load_settings -VERSION_PREFIX=$(eval "echo `git config --get gitflow.prefix.versiontag`") -PREFIX=$(git config --get gitflow.prefix.support) +init() { + require_git_repo + require_gitflow_initialized + gitflow_load_settings + 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!" warn "note: DO NOT use it in a production situation." @@ -167,12 +169,12 @@ cmd_start() { # fetch remote changes if flag fetch; then - git fetch -q "$ORIGIN" "$BASE" + git_do fetch -q "$ORIGIN" "$BASE" fi require_branch_absent "$BRANCH" # create branch - git checkout -b "$BRANCH" "$BASE" + git_do checkout -b "$BRANCH" "$BASE" echo echo "Summary of actions:" diff --git a/gitflow-common b/gitflow-common index 4834cf102..332740533 100644 --- a/gitflow-common +++ b/gitflow-common @@ -70,6 +70,14 @@ noflag() { local FLAG; eval FLAG='$FLAGS_'$1; [ $FLAG -ne $FLAGS_TRUE ]; } # Git specific common functionality # +git_do() { + # equivalent to git, used to indicate actions that make modifications + if flag show_commands; then + echo "git $@" >&2 + fi + git "$@" +} + 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/^[* ] //'; }