Skip to content

Commiting to Git

Chloe edited this page May 10, 2024 · 16 revisions

Branching Model & Workflow details

+---------+       +-------------------+
|  Main   |<------+   Hotfix Branch   |
+----^----+       +--------^----------+
     |                     |
     |                     |
     |               +-----+------+
     +-------------> |   Feature  |
                     |   Branch   |
                     +------------+
  • Main Branch: As the name says, the main branch, which is to be stable, tested version → main/
  • Feature Branch: Derived from the main branch. For ongoing development, connected sets of changes, merged back into main once reviewed. These branches should preferably be short lived to minimise divergence from the main branch. → feature/
  • Hotfix Branch: Used for critical bug fixes on main. After the fix, they should be merged back into both the main and feature branches to ensure that the fix is added into the ongoing development process. → hotfix/

Branch Management

Creating Branches

Always create a new branch for each new feature or bug fix, so the code stays organized and isolated from the main codebase.

Naming the Branches

  • Always follow the formatting style to maintain cleanliness and consistency, and to prevent the pre-commit hook from flagging it.

Example of a good branch name

  • The branch follows the feature/ naming convention when adding in new features.
  • The branch has a good descriptive name.

Example of a bad branch name:

  • The branch does not follow the formatting style, and pre-hook will flag this now, preventing you from pushing it to the repository.

Life Cycle of Branches

  • Feature Branches: Merge feature branches back into the main branch once the feature is complete, tested, and reviewed.
    • Ideally we want to avoid long lived branches, which can accumulate a significant number of changes, making merging difficult to do.
  • Hotfix Branches: These branches should be merged back as soon as the fix is complete and verified.
  • Regular Maintenance: Every now and then to go back and check on the unused braches and review them to see if they should be deleted as this can make the repository a lot cleaner.

Deleting Branches

  • After a branch has been successfully merged into main, it should be deleted to keep the repository clean and manageable.

Version Control Best Practices

  • Consistent Pulls: Regularly pull from the main branch to keep your feature branches up-to-date.
  • Protect Main Branch: We do not allow direct pushes to the main branch, insteas we use pull requests to merge changes, making sure that they are reviewed and tested before integration.
  • Atomic Commits: Make sure each commit is self-contained and can be understood on their own.
  • Branch Deletion: As mentioned above, regularly delete old branches that have been merged or abandoned to keep your repository organized.

Making Good Commits

  • Try to make smaller, but more frequent commits throughout the day, as it's easier to fix and review

  • Add a descriptive message of what kind of changes were made, and why they were neccessary

  • Use prefixes in commit messages:

    • When ADDING a new function

      ADD: < what has been added >
    • When FIXING an error

      FIX: Bug < [what bug] > [description]
    • When REMOVING code, files

      DEL: < what has been removed >
    • When UPDATING something

      UPD: < what has been updated >

  • Committing not fully-functional additions is possible if all tests pass and nothing breaks because of it.
  • Every commit should be logically connected to one another, if it contains the word and, split it into multiple commits
  • Use the git add -p command to prepare and verify the contents of the commit before finalizing it and git diff --cached to review
  • Avoid force push unless really neccessary

Good vs. Bad Commit Examples

  • Some tips about writing helpful commit messages:
    • Separate the title from the body with a blank line
    • Subject line <= 50 characters + imperative mood
    • Use the body to explain what and why vs. how.
    • Body <= 72 characters + why and how

Good Commit Example:

Why it’s good:

  • Clear Prefix: Uses a prefix "UPD" to indicate that it's an update, which is part of the standard convention.
  • Descriptive: Clearly describes what was done (updating a YAML file) and why (to include an update option).
  • Scope Limited: Focuses on a single change which makes it easier to understand the purpose and impact of the commit.

Bad Commit Example:

Why they’re bad:

  • Non-descriptive Messages: The commit messages are vague, do not convey the purpose of the changes.
  • Inconsistent Naming: They do not follow a clear or agreed-upon naming convention which makes them harder to track in the version history. (granted this did not exist back then, but it is the best example I have now, sorry Julius)
  • Should Have Been Squashed: We have opted to squash merge to maintain a clean history, however this was merged as singular commits, making it more difficult to maintain a clean history.

Handling Merge Conflicts

  • Merge conflicts can arise when multiple branches have edited the same part of the same file. Here's how to resolve them:
    • Use git mergetool: This will opens a GUI that you can use to resolve conflicts manually. Configure your preferred tool in your Git configuration with git config --global merge.tool <toolname>.
    • Manual Resolution: Open the conflict and look for the lines marked with conflict markers (<<<<<<<, =======, >>>>>>>). Edit the file to fix the conflicts, then click git add the file to mark it as resolved.
    • Command Line: Alternatively, you can solve the conflict through the command line

Rebasing vs. Merging

  • Know when to rebase and when to merge to maintain a clean and efficient project history:
    • Use git rebase for Feature Branches: Before creating a pull request (PR), rebase your feature branch onto the latest commit of the Main branch. This practice helps create a nicer history, which simplifies both navigation and troubleshooting in the project history. Also when updates from Main branch are added into the feature branch you can spare merge conflicts.
    • Use Pull Requests for Integrating Completed Features and Hotfixes: Once the feature or hotfix branch is fully tested and approved, squash merge it back into the Main branch using a pull request.

Interactive Rebasing

  • Cleaning Up Commits: You can use git rebase -i for interactive rebasing, which allows you to modify commits: rewrite, delete, and squash commits before they are merged into main.

Additional Tips:

  • Rebasing Best Practices: Always pull and rebase (git pull --rebase) your feature branches before pushing your changes to remote repositories to minimize conflicts and ensure your branch is up to date with the Main branch. This step should always be completed before opening a new pull request.

Using git stash

  • Managing Changes: Use git stash to save your current state temporarily if you need to switch branches without committing half-done work. This is also super helpful in maintaining a clean history.

    • Stash Your Changes: Use git stash and clean your working directory, putting it back to the last commit state.

    • List Stashed Changes: Use git stash list to view all stashed changesets.

    • Apply Stashed Changes: Use git stash pop to apply the most recently stashed changes and remove them from the stash. Alternatively, git stash apply applies the changes but keeps them in the stash for potential re-use.

    • Clearing Stashes: When you no longer need the stashed changes, you can clear your stash with git stash clear to keep your stash list clean.

Git Hooks

To maintain our standards for commit messages and branch names, we utilize Git Hooks.

Commit-msg Hook

There is a hook in place to prevent the team from doing commit messages that are not aligned with our designated format. ADD:, FIX:, DEL:, or UPD:

This script will automatically check the format of your commit messages. If a commit message does not adhere to the format, the commit will be rejected until corrected.

Setting Up the Commit Message Hook

  1. Navigate to the hooks directory:
cd .git/hooks
  1. Create or edit the commit-msg file:

    • To create or open the file in a terminal:

      touch commit-msg
    • If you prefer using Visual Studio Code:

      code commit-msg
  2. Add the following script to it:

#!/bin/sh
# Check if the commit message follows our agreed on format

# Read the commit message from file
commit_message=$(cat $1)

# Check if commit message follows format
if ! echo "$commit_message" | grep -Eq '^(ADD:|FIX:|DEL:|UPD:) .+'
then
    echo "Invalid commit message: '$commit_message'"
    echo "Commit messages must start with ADD:, FIX:, DEL:, or UPD: e.g. ADD: New feature"
    exit 1
fi

echo "Commit message follows format."
  1. Make the script executable:
chmod +x commit-msg

Pre-push Hook for Branch Names

This hook is in place to maintain a consistency between all of the branch names that we have so we do not have situations such as:

  • feature/
  • feat/
  • features/

This hook ensures that all branch names adhere to our naming convention: main, feature/, or hotfix/.

Setting Up the Pre-push Hook

  1. Navigate to the hooks directory:
cd .git/hooks
  1. Create or edit the pre-push file:

    • To create or open the file in a terminal:

      touch pre-push
    • If you prefer using Visual Studio Code:

      code pre-push
  2. Add the following script to it:

#!/bin/sh
# Check if branch name follows our agreed on format

# Get current branch name
branch_name=$(git rev-parse --abbrev-ref HEAD)

# Check if the branch name fits format
if ! echo "$branch_name" | grep -Eq "^(main|feature/.+|hotfix/.+)$"; then
    echo "Error: Branch name '$branch_name' does not fit our naming convention"
    echo "Allowed patterns: 'main', 'feature/*', 'hotfix/*'"
    exit 1
fi

echo "Branch name fits naming convention."
exit 0
  1. Make the script executable:
chmod +x pre-push

How to Rename an Incorrectly Named Branch

If the pre-push hook flags your branch as incorrectly named, you can do so with the following command before pushing:

git branch -m new-branch-name
  • Replace new-branch-name with the correct format following our naming convention.
  • After renaming the branch, you can proceed with your push, and the pre-push hook will validate the new name.

Helpful Resources

Clone this wiki locally