As a developer, you often find yourself working on a new feature or fix in the main codebase branch, usually master. After making some changes, you realize you should have created a separate branch for that work. However, since the changes are uncommitted, you don‘t want to lose them. Luckily, Git provides a simple way to move all uncommitted work to a new branch.

Why Create Feature Branches?

There are a few key reasons for moving existing uncommitted work to a new branch:

  • Keep mainline branches clean – The master or main branches should contain shippable code, ready for release at any time. Unfinished, experimental work should happen in feature branches.

  • Separate concerns – Branches let you context switch between different tasks or ideas. Compartmentalization reduces complexity.

  • Preserve work in progress – By diverting changes to a branch, you don‘t lose anything already done.

  • Facilitate pull requests – Branches cleanly capture a related set of commits for code review and integration.

Branching is a pivotal Git workflow tool for any non-trivial project. In Stack Overflow‘s 2021 survey, over 90% of developers reported using Git, underscoring its widespread adoption. Branching and merging enables developers to collaborate efficiently on the same codebase.

According to the authoritative Git Book published by Git itself:

Branching means you diverge from the main line of development and continue to do work without messing with that main line.

So why isn‘t all development done directly on master? Long-running experiments may destabilize the code or feature toggles complicate testing. Branch-based development compartmentalizes changes related to a task, bug fix, or concept.

Proper use of branchingstrategies also leads to higher quality software.

Viewing File Changes

Before moving anything, let‘s inspect existing uncommitted changes. Navigate to the local Git repository in the terminal then run:

git status

This displays working tree changes divided into files that are:

  • Untracked – Unknown to Git and not staged for commit yet. Usually newly created files.

  • Modified – Known to Git but contain changes that are unstaged. Existing tracked files with edits.

  • Staged – Changes explicitly flagged and ready to commit.

For example:

On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   src/App.js

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        new-feature.js

Here src/App.js contains staged changes ready to commit. README.md shows modified but unstaged changes. And new-feature.js is an untracked file. Next, we‘ll move all changes to a new branch.

Creating a Branch

Creating a branch is fast and easy in Git. Use git checkout with the -b flag:

git checkout -b new-branch

This simultaneously creates and switches to the branch called new-branch.

An alternative is using git switch introduced in Git 2.23:

git switch -c new-branch

The key things to note are:

  • checkout/switch: Move the HEAD reference pointer to the branch and update working directory files.
  • -b/ -c: Pass this option to create the branch if it doesn‘t already exist.

These commands provide a shortcut to link working directory changes to a new branch instantly.

Git branching visualization

Changing branches with Git checkout or switch (Source)

Conceptually branches represent diverging timelines of commits across parallel universes. By switching position with HEAD, you expose files tracked in that particular line of commits.

How Checkout vs Switch Compares

git checkout and git switch offer similar functionality for changing branches, with some key differences:

Operation Checkout Switch
Change branches Yes Yes
Create new branches Yes Yes
Restore files from HEAD Yes No

git restore replaces git checkout -- <file> for discarding changes in the Git 2.23+ release. Using switch signals the intent to only change branches, while checkout does double duty.

Overall switch offers a more focused, dedicated command improving clarity. Checkout has been around longer so still useful for restoring files when needed.

Confirm Branch Creation

After creating a branch, verify it exists by running git branch. This prints all branch references:

main
* new-branch

The preceding * indicates the current HEAD position – in this case, pointing to new-branch.

Rename branches with:

git branch -m new-name

Descriptive names categorize work such as feature/new-modal or bug/login-error. Well organized branches simplify management of a repository with many divergent efforts.

According to hosting service GitHub‘s recommendations in their blog:

Branch names should be all lowercase, with words separated by hyphens (-).

Adhering to conventions like these makes collaboration easier.

Preserving Uncommitted Changes

The major outcome is uncommitted work transfers over to the new Git branch. Check files match the earlier git status output.

If previously untracked, those same files now show under changes not staged for commit:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md
        new-feature.js

Modifications also persist intact after the branch changeover. However, changes still need to be added and committed as usual.

Existing edits seamlessly divert to the new branch without losing work in progress. This enables context switching between multiple efforts by compartmentalizing changes.

Integrating Changes Via Pull Requests

After completing a feature or fix, integrate changes back into main via a pull request (PR). This issues a merge commit applied to the base branch, fast-forwarding its commit history.

Merging Git feature branch

Merging a topic branch into main via pull request

The PR consolidates all commits associated with the branch into mainline. After approval and merging, delete the branch reference to keep the environment tidy.

Weighing Git Merge Strategies

When integrating branches, there are a few merge techniques to consider:

Method Description Pros Cons
Fast forward Move pointer forward Simple, linear history Doesn‘t preserve branch point
No fast forward Always generate merge commit Capture branch history More merge commits
Rebase Re-apply commits Clean commit tree Rewrites history

Fast forward directly plays forward main if possible, while no fast forward forces a merge commit. Rebasing replays branch changes on top of main updates.

There are valid use cases for each depending on the development flow style preferred.

Summary

Moving uncommitted work into a new Git branch avoids losing changes and separates ongoing efforts.

  • Use git checkout -b or git switch -c to swiftly create a branch and switch active files
  • All uncommitted edits carry over to the new branch worktree
  • Name branches clearly for organizational purposes
  • Integrate via pull request once work completes
  • Delete branch after merging to main

Branch-based development takes time to get used to but soon feels second nature. This unlocks decentralized workflows enabling developers to collaborate efficiently on the same codebase.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *