GitFlow模式下,如何用Git Hooks创建Release分支时自动更新版本号?
Great question! I’ve tackled similar GitFlow automation before, so let’s walk through how to make this work perfectly. The post-checkout hook is indeed the right tool here—we just need to nail down the parameter checks and branch name logic.
First: Understand post-checkout Hook Parameters
The post-checkout hook receives three positional arguments every time it runs:
$1: The SHA-1 hash of the previous HEAD (the commit you were on before checkout)$2: The SHA-1 hash of the new HEAD (the commit you’re now on after checkout)$3: A flag (1if you switched branches,0if you just checked out specific files)
Key Checks to Identify a New Release Branch Creation
To tell if we’re creating a new Release branch (not just checking out an existing one), we can rely on two clues specific to GitFlow’s branch creation workflow:
- When you run
git checkout -b release/x.y.z, the new branch points to the same commit as your current HEAD (so$1will equal$2). - The new branch name follows GitFlow’s convention: it starts with
release/.
Step-by-Step Hook Implementation
1. Create/Edit the post-checkout Hook
Navigate to your repo’s .git/hooks directory and create (or edit) the post-checkout file. Make sure it’s executable later with chmod +x post-checkout.
2. Add the Hook Logic
Here’s a complete script with comments explaining each part:
#!/bin/bash # Grab the hook parameters prev_head="$1" new_head="$2" is_branch_switch="$3" # Exit early if we're not switching branches (e.g., checking out files) if [ "$is_branch_switch" -ne 1 ]; then exit 0 fi # Exit early if we're checking out an existing branch (prev and new HEAD differ) if [ "$prev_head" != "$new_head" ]; then exit 0 fi # Get the name of the current branch we just switched to current_branch=$(git rev-parse --abbrev-ref HEAD) # Exit early if this isn't a GitFlow Release branch if [[ ! "$current_branch" =~ ^release/ ]]; then exit 0 fi # Extract the version number from the branch name (strip "release/") version="${current_branch#release/}" # Define the file you want to update (replace with your actual file path) version_file="version.txt" # Update the version number in the file (adjust the sed pattern to match your file's format) # Example: Replaces lines starting with "Version: " with the new version # Note: On macOS, sed requires the backup extension (.bak), remove it for Linux sed -i.bak "s/^Version: .*/Version: $version/" "$version_file" rm -f "${version_file}.bak" # Clean up the backup file # Stage and commit the version bump git add "$version_file" git commit -m "Automatically bump version to $version for new release branch" echo "Successfully updated version to $version in $version_file"
3. Customize for Your Project
- Replace
version.txtwith the actual file path where your version is stored (e.g.,src/__init__.py,package.json). - Adjust the
sedpattern to match how version numbers are formatted in your file. For example, if yourpackage.jsonhas"version": "x.y.z", use:sed -i.bak "s/\"version\": \".*\"/\"version\": \"$version\"/" package.json
How It Works
- When you run
git checkout -b release/1.2.3fromdevelop, the hook detects:- We switched branches (
$3 = 1) - The previous and new HEAD are the same (we created a new branch from the current commit)
- The branch starts with
release/
- We switched branches (
- It extracts
1.2.3as the version, updates your target file, commits the change automatically.
Edge Cases to Consider
- If someone creates a Release branch with
git branch release/x.y.zthen checks it out later: The hook won’t trigger ongit branch, but will trigger ongit checkout release/x.y.z—but since$1 != $2(you’re switching from another branch to the existing release branch), the script exits early. To handle this, you could add an extra check for whether the branch was just created (usinggit reflogto look for "branch: Created from ..."), but that’s more complex and usually unnecessary for standard GitFlow workflows. - Ensure the hook has executable permissions: Run
chmod +x .git/hooks/post-checkoutif you get "permission denied" errors.
内容的提问来源于stack exchange,提问作者Rui Bastos

