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.

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.

Deleting Branches

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

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.

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

Helpful Resources

Clone this wiki locally