Extremely Serious

Category: Git (Page 1 of 2)

A Practical Workflow for Git Worktrees in Everyday Development

Git worktrees provide a clean, efficient way to work on multiple branches at once without juggling stashes, temporary commits, or extra clones. This article walks through a concrete workflow for adopting git worktree in everyday development.


Why git worktree?

In a typical Git workflow, switching branches while you have uncommitted work forces you to choose between stashing, WIP commits, or creating another clone of the repository. Git worktrees give you another option: multiple checked‑out branches from the same repository, each in its own directory, sharing a single .git data store.

This is especially useful when:

  • You frequently interrupt a feature for hotfixes, reviews, or experiments.
  • Your project has heavy dependencies (node modules, large virtualenvs, Gradle caches), making multiple clones expensive.
  • You want to run tests or builds for several branches in parallel on the same machine.

One‑time setup and conventions

Start from an existing clone of your repository, with main (or develop) checked out:

git worktree list

Initially, you should see only the main worktree (the directory you’re in), showing its path, commit, and branch.

Choose a consistent convention for worktree locations, such as:

  • A .worktrees/ directory inside the main repo (e.g. .worktrees/feature-new-ui).
  • Or sibling directories (e.g. ../project-feature-new-ui).

The important part is that each worktree has a unique, meaningful path and that you avoid nesting one Git worktree inside another, which can confuse Git’s metadata.


Creating a worktree for an existing branch

Suppose your remote has a branch feature/new-ui that you want to work on without leaving main in your primary directory.

From the main repo directory:

git fetch origin
git worktree add .worktrees/new-ui feature/new-ui
cd .worktrees/new-ui

Key points:

  • git worktree add <path> <branch> creates a new directory at <path> and checks out <branch> there.
  • The new directory behaves like a normal working copy: you edit files, run tests, commit, and push as usual.

Your typical flow inside that worktree looks like:

# already in .worktrees/new-ui
git status
# edit files, run tests
git commit -am "Implement new UI"
git push -u origin feature/new-ui

When you’re done for now, you can simply cd back to the main directory, which still has your original branch and working state untouched.


Starting a new feature in its own worktree

Very often, the branch doesn’t exist yet; you want to create it and work in a dedicated directory from the start.

From the main repo directory:

git fetch origin
git worktree add -b feature/new-api .worktrees/new-api origin/main
cd .worktrees/new-api

Here:

  • -b feature/new-api tells Git to create feature/new-api as a new branch.
  • origin/main is the base commit; you can use main, develop, or any other starting point appropriate to your branching model.

Now you can develop the feature completely within .worktrees/new-api, while the main directory remains on main for reviews, builds, or other work.


Managing multiple active worktrees

Over time, you might accumulate several active worktrees: a couple of feature branches, a long‑running refactor, and maybe a release branch.

To see what’s active:

git worktree list

The output lists each worktree’s path, current commit, and checked‑out branch, with the main worktree first. For example:

/home/user/project                     a1b2c3d [main]
/home/user/project/.worktrees/new-ui   d4e5f6 [feature/new-ui]
/home/user/project/.worktrees/new-api  987654 [feature/new-api]

With this view you can:

  • Jump between directories instead of switching branches in a single directory.
  • Keep long‑running work (like big refactors) open and test them periodically without disturbing your day‑to‑day branch.
  • Run multiple test suites or build processes in parallel on different branches.

Each worktree is a self‑contained environment for that branch; there is no “one worktree, many branches” mode—every worktree corresponds to a single branch or detached HEAD at a time.


Handling urgent hotfixes and reviews

A classic use case: you’re mid‑feature when a production incident appears.

Instead of stashing or committing half‑baked work:

  1. Leave your feature worktree as is.

  2. From the main repo directory, create a hotfix worktree:

    git fetch origin
    git worktree add .worktrees/hotfix-critical hotfix/critical-bug
    cd .worktrees/hotfix-critical
  3. Apply the fix, commit, and push:

    # implement fix
    git commit -am "Fix critical bug in production"
    git push origin hotfix/critical-bug
  4. Once the hotfix is merged back into main and any release branches, you can remove this worktree (see next section).

You can use the same pattern for:

  • Checking out a PR branch to test it locally.
  • Pairing on a branch without touching your current environment.
  • Running experiments on a throwaway branch in a dedicated directory.

Cleaning up: remove and prune

Worktrees are cheap, but they will accumulate if you never remove them.

Once a branch is merged and you no longer need its dedicated directory:

# from the main repo directory (or any worktree in the same repo)
git worktree remove .worktrees/new-ui

Important details:

  • git worktree remove <path> removes the worktree directory and its administrative entry; it does not necessarily delete the Git branch itself.
  • The worktree must be clean (no untracked or modified tracked files) unless you add --force, which will discard uncommitted changes.

Over time you may manually delete directories or encounter stale entries (e.g. after a crash). To clean up those leftovers:

git worktree prune --verbose

This command prunes worktree records whose directories no longer exist, using expiration rules that can be configured via Git settings like gc.worktreePruneExpire. You can also use --expire <time> with prune if you want to only remove older, unused entries.

A light maintenance habit is:

  • Remove the worktree for a feature once its PR is merged and the branch is closed.
  • Run git worktree prune occasionally to clean up stale metadata.

Practical guidelines and best practices

To make git worktree a reliable part of your team’s workflow, adopt a few simple rules:

  • Organize worktrees predictably: Use stable directory patterns (.worktrees/<branch-name> or similar) and use names that reflect the branch, like .worktrees/feature-auth-api.
  • Avoid nesting: Never create a worktree inside another worktree’s directory; this can confuse Git’s detection of repositories and worktrees.
  • Keep your base branches fresh: Regularly fetch and update main/develop and rebase or merge them into your feature worktrees to minimize integration surprises.
  • Clean up after merges: Remove worktrees you no longer need, then prune occasionally to ensure git worktree list remains readable and accurate.
  • Check Git version: Some newer options and behaviors (like more detailed list output and improved prune behavior) depend on having a reasonably up‑to‑date Git installation.

By following this workflow—create a worktree per active branch, keep them organized, and clean them up when done—you get parallel branch development with far less friction than stashes, temporary commits, or multiple clones, while still relying on standard Git primitives.

Squashing Commits with git merge

Introduction

In Git, squashing commits is a powerful technique that combines multiple commits into a single, more concise commit. This can simplify your project's history and make it easier to review changes. One common method to achieve this is using the git merge --squash command.

Understanding git merge --squash

When you use git merge --squash, Git merges the changes from the source branch into the target branch, but instead of creating a new commit for each merged change, it creates a temporary commit that contains all the changes combined. This temporary commit is not automatically recorded in the history.

Steps to Squash Commits

  1. Switch to the target branch:

    git checkout <target-branch>
  2. Merge the source branch:

    git merge --squash <source-branch>
  3. Review the merged changes:

    git diff
  4. Create the final commit:

    git commit -m "Squashed commits from "

Example

Let's say you have a feature branch named feature-branch and you want to merge its changes into the main branch. Here's how you would use git merge --squash:

git checkout main
git merge --squash feature-branch
git commit -m "Merged feature changes"

Benefits of Squashing Commits

  • Cleaner history: Reduces the number of commits, making it easier to review changes.
  • Improved readability: A concise commit history can be easier to understand and navigate.
  • Simplified code review: Fewer commits to review can streamline the code review process.

When to Squash Commits

  • Small, related changes: If you've made a series of small, related changes, squashing them into a single commit can provide a better overview.
  • Experimental or temporary changes: If you've made changes that were experimental or temporary, squashing them can clean up the history.
  • Before creating a pull request: Squashing commits before submitting a pull request can help keep the review process focused.

Caution:

While squashing commits can be beneficial, it's important to use it judiciously. If you need to track individual commits for debugging or auditing purposes, consider merging normally instead of squashing.

Conclusion

git merge --squash is a valuable tool for maintaining a clean and organized Git history. By understanding how to use it effectively, you can streamline your development workflow and improve the readability of your project's changes.

Set the SSL Backend to use with Git

To provide which ssl backend to use with git use the following syntax:

git config --global http.sslBackend <SSL_BACKEND>

The SSL_BACKEND token can potentially be openssl or schannel.

schannel uses the windows certicate store.

Example

git config --global http.sslBackend schannel

Useful Environment Variable for Git Troubleshooting

VariableDescriptionPossible Values
GIT_CURL_VERBOSETells Git to emit all the messages generated by that library. This is similar to doing curl -v on the command line.1
GIT_SSL_NO_VERIFYTells Git not to verify SSL certificates.true
GIT_TRACEControls general traces1, 2 or true
GIT_TRACE_PACKETEnables packet-level tracing for network operations.true

Squashing Commits Before Pushing a Branch into a Git Upstream

Pre-requisite

  • Git is installed locally.

Procedures

  1. Checkout the non-master branch to be squashed.
  2. Ensure that the branch is up to date from the master.
  3. Open a terminal and change the directory to the root of checked out branch.
  4. Run the following command:
    git rebase -i master
  5. Once a text editor opens and leave the first pick alone and the subsequent picks must be replaced with squash. For example:
    From

    pick < hash1 > < message1 >
    pick < hash2 > < message2 >
    pick < hash3 > < message3 > 
    pick < hash4 > < message4 >
    

    To

    pick < hash1 > < message1 >
    squash < hash2 > < message2 >
    squash < hash3 > < message3 > 
    squash < hash4 > < message4 >
    
  6. Save the update and close the editor.
  7. Another editor will open to update the message since git is about the combine multiple commits.
  8. Update the message if necessary.
  9. Save and close the editor.
  10. If everything went fine your branch is now squashed.

Pushing files with More than 1MB in Size via HTTP in Git

For some reason, you have files with more than 1MB in total size to push to git respository by HTTP. You might be surprised that you cannot do it. This is because by default, git only posts to remote server via HTTP protocol with a maximum of 1MB. To remedy this, increase the http.postBuffer to 500MB (i.e. if you have to send files with 500MB total size) on client side like the following:

git config --global http.postBuffer 524288000

Reference

https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-config.html

Git for Windows Credentials

The location for git for windows credentials can be found in the Credential Manager of windows. You can use this manager to add, remove or delete a git credential.

This can be accessed from the Control Panel then click the User Accounts. From there, click Credential Manager.

Control Panel -> User Accounts -> Credential Manager

Normally the credential manager looks like the following:

« Older posts