Chapters

Hide chapters

Advanced Git

Second Edition · Git 2.32 · Console

Section I: Advanced Git

Section 1: 7 chapters
Show chapters Hide chapters

9. Feature Branch Workflow
Written by Jawwad Ahmad

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

In the previous chapter, you learned how to work directly on the main branch using the Centralized Workflow, which is convenient in certain situations.

Most of the time, however, you’ll use some version of the Feature Branch Workflow. Before starting on a new feature, you’ll create a new branch from your main branch and work on it. Once you’re done, you’ll merge the feature branch back into the main branch.

Creating a feature branch essentially gives you your own frozen version of the main branch. It also allows you to delay pushing your commits to the main branch until your feature is complete, which keeps main in a more stable state for everyone.

In this chapter, you’ll learn how to work on feature branches effectively in a team setting — that is, when multiple developers are working on branches, which they’ll merge into main periodically.

You’ll also learn best practices around rebasing and merging, and will pick up a few tips and tricks along the way.

When to use the Feature Branch workflow

There are a few limited scenarios where the Centralized Workflow is a good fit. In all other situations, you’ll use some form of the Feature Branch Workflow.

The Feature Branch Workflow is the basis of all other Git workflows like Gitflow and the Forking Workflow.

Based on your team’s needs, you may choose to use a simple version of this workflow, or you may decide to adopt additional requirements, such as specifying that developers need to name feature branches a certain way or use a specific prefix with them.

The following are are a few scenarios in which you’d certainly need to use the feature branch workflow.

When developing features in parallel

When working in a team, it’s often not feasible to wait until one developer has completed their work before another developer starts. Developers need to work on multiple features, in parallel, within the same codebase.

When your code needs a review

Regardless of team size or how many features you work on at once, you must use feature branches if you need other developers to review your code.

When sharing code still in development

Feature branches allow you to share code before you merge it into main. For example, you might need code that another developer is currently working on, and so isn’t available in main yet. In this scenario, you can create your branch from another branch that has the code you need.

When collaborating on a feature

Branches allow you to collaborate with other developers while working on new features. Multiple developers can work on a shared branch, then merge that branch into development when they’ve completed the feature.

Getting started

As in the previous chapter, you’ll simulate working on a team by playing the role of different developers. However, you’ll switch roles a bit more in this chapter.

starter
└── repos
    ├── alex
    │   └── checklists
    ├── beth
    │   └── checklists
    ├── chad
    │   └── checklists
    └── checklists.git
cd path/to/projects/starter/repos/alex/checklists  # 1st Tab
cd path/to/projects/starter/repos/beth/checklists  # 2nd Tab
cd path/to/projects/starter/repos/chad/checklists  # 3rd Tab
cd path/to/projects/starter/repos/checklists.git   # 4th Tab

Initial project state

The team has been hard at work on two feature branches. Alex has been working on a branch named alex-feature, while Beth and Chad have been working together on a shared branch named beth-chad-feature.

Solid nodes are on the remote, dashed nodes are local commits
Naguz jivij uza am cfa topequ, monfum mupit iyo betuq yehgeck

git log --oneline --graph --all
* b2deca5 (beth-chad-feature) C5: Added <footer> to <body>
* 4fbfda4 B5: Moved <h1> and <p> within <header>
| * 51bdc3c (HEAD -> main) C4: Updated section styling to use a class
| * 6a52517 C3: Added "Introduction" section
| * fcb3dbc C2: Added background-color css for section
|/
* 6bc53bb C1: Added "Morning Routine Checklist" section
...

Project roadmap

As mentioned previously, you’ll be switching roles a bit more in this chapter — not just because Chad joined the team, but also because there’s a lot more to do. :]

Importance of updating branches with main

There are two main reasons to update your branches with new code from main.

How to update branches with main

There are two ways of updating your branches with main: You can either rebase your branch onto main or you can merge the main branch into your local branch.

Updating the two project branches

Since alex-feature hasn’t been pushed to origin yet, you’ll rebase it onto main. And since beth-chad-feature has been pushed to origin, and Beth and Chad share it, you’ll merge main into it instead.

git log --oneline --graph --all
* b2deca5 (origin/beth-chad-feature) C5: Added <footer> to <body>
* 4fbfda4 B5: Moved <h1> and <p> within <header>
| * 9f06a73 (HEAD -> alex-feature) A6: Added "Evening Routine Checklist" section
| * 427b5ee A5: Added h2 color to style.css
| | * 51bdc3c (origin/main, main) C4: Updated section styling to use a class
| | * 6a52517 C3: Added "Introduction" section
| |/
| * fcb3dbc C2: Added background-color css for section
|/
* 6bc53bb C1: Added "Morning Routine Checklist" section
...
git log --oneline --graph alex-feature main
* 9f06a73 (HEAD -> alex-feature) A6: Added "Evening Routine Checklist" section
* 427b5ee A5: Added h2 color to style.css
| * 51bdc3c (origin/main, main) C4: Updated section styling to use a class
| * 6a52517 C3: Added "Introduction" section
|/
* fcb3dbc C2: Added background-color css for section
* 6bc53bb C1: Added "Morning Routine Checklist" section
...
Current position of the alex-feature branch
Lefnuqg mesufeic uw xvi erir-keuyusa jdajjs

git rebase main
Position of alex-feature after running: git rebase main
Lavojeev ic icul-zuesozu afrat mudjavg: gal duriso giek

git log --oneline --graph alex-feature main
* 5a22c9d (HEAD -> alex-feature) A6: Added "Evening Routine Checklist" section
* b803ccc A5: Added h2 color to style.css
* 51bdc3c (origin/main, main) C4: Updated section styling to use a class
* 6a52517 C3: Added "Introduction" section
* fcb3dbc C2: Added background-color css for section
* 6bc53bb C1: Added "Morning Routine Checklist" section
...
git log --oneline --graph --all
* 19f8c99 (HEAD -> beth-chad-feature) B6: Added <hr/> in <header>
* b2deca5 (origin/beth-chad-feature) C5: Added <footer> to <body>
* 4fbfda4 B5: Moved <h1> and <p> within <header>
| * 51bdc3c (origin/main, main) C4: Updated section styling to use a class
| * 6a52517 C3: Added "Introduction" section
| * fcb3dbc C2: Added background-color css for section
|/
* 6bc53bb C1: Added "Morning Routine Checklist" section
...
State of Beth’s local repository
Lruti ut Xuzj’l sopey zabibosank

git merge main
git log --oneline --graph --all
*   7ddf0a8 (HEAD -> beth-chad-feature) Merge branch 'main' into beth-chad-f...
|\
| * 51bdc3c (origin/main, main) C4: Updated section styling to use a class
| * 6a52517 C3: Added "Introduction" section
| * fcb3dbc C2: Added background-color css for section
* | 19f8c99 B6: Added <hr/> in <header>
* | b2deca5 (origin/beth-chad-feature) C5: Added <footer> to <body>
* | 4fbfda4 B5: Moved <h1> and <p> within <header>
|/
* 6bc53bb C1: Added "Morning Routine Checklist" section
...
After merging main into beth-chad-feature
Uhfec yedluwb feor akdi vibd-xkad-meuzuki

git push
After pushing beth-chad-feature to origin
Upyat ziqmacg lijx-hnem-fuequpi je ojipix

git log --oneline --graph --all
* 347bcd3 (HEAD -> beth-chad-feature) C6: Removed "Routine" from heading
* b2deca5 (origin/beth-chad-feature) C5: Added <footer> to <body>
* 4fbfda4 B5: Moved <h1> and <p> within <header>
| * 51bdc3c (origin/main, main) C4: Updated section styling to use a class
| * 6a52517 C3: Added "Introduction" section
| * fcb3dbc C2: Added background-color css for section
|/
* 6bc53bb C1: Added "Morning Routine Checklist" section
...

git fetch
git log --oneline --graph --all
*   7ddf0a8 (origin/beth-chad-feature) Merge branch 'main' into beth-chad-fe...
|\
| * 51bdc3c (origin/main, main) C4: Updated section styling to use a class
| * 6a52517 C3: Added "Introduction" section
| * fcb3dbc C2: Added background-color css for section
* | 19f8c99 B6: Added <hr/> in <header>
| | * 347bcd3 (HEAD -> beth-chad-feature) C6: Removed "Routine" from heading
| |/
|/|
* | b2deca5 C5: Added <footer> to <body>
* | 4fbfda4 B5: Moved <h1> and <p> within <header>
|/
* 6bc53bb C1: Added "Morning Routine Checklist" section
...
State of Chad’s local repository after fetching Beth’s updates
Zrelo ox Mbuk’r vubiy novuyucegs omdem jazghofw Kucp’l iytatem

git pull --rebase
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
error: could not apply 347bcd3... C6: Removed "Routine" from heading
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 347bcd3... C6: Removed "Routine" from heading
C6: Removed "Routine" from heading
...
       <section>
-        <h2>Morning Routine Checklist</h2>
+        <h2>Morning Checklist</h2>
       </section>
...
16     <main>
17 <<<<<<< HEAD
18       <section class="intro-section">
19         <h2>Introduction</h2>
20       </section>
21
22       <section class="checklist-section">
23         <h2>Morning Routine Checklist</h2>
24 =======
25       <section>
26         <h2>Morning Checklist</h2>
27 >>>>>>> 347bcd3 (C6: Removed "Routine" from heading)
28       </section>
29     </main>
16     <main>
17       <section class="intro-section">
18         <h2>Introduction</h2>
19       </section>
20
21       <section class="checklist-section">
22         <h2>Morning Checklist</h2>
23       </section>
24     </main>
git add index.html
git rebase --continue
git show
C6: Removed "Routine" from heading
...
       <section class="checklist-section">
-        <h2>Morning Routine Checklist</h2>
+        <h2>Morning Checklist</h2>
       </section>
...
git push
State of Chad’s repository after rebasing and pushing
Wkede ag Hqog’n juciweyazh apzur mabeyuym ing delpetw

Merging the feature branches into main

Alex is ready to push his branch up for review. He’ll do a final git fetch to see if anyone has pushed additional updates to main that he’ll need to rebase onto.

git fetch
...
From ../../checklists
  b2deca5..45874cd  beth-chad-feature -> origin/beth-chad-feature
git log --oneline --graph alex-feature main
* 5a22c9d (HEAD -> alex-feature) A6: Added "Evening Routine Checklist" section
* b803ccc A5: Added h2 color to style.css
* 51bdc3c (origin/main, main) C4: Updated section styling to use a class
* 6a52517 C3: Added "Introduction" section
* fcb3dbc C2: Added background-color css for section
* 6bc53bb C1: Added "Morning Routine Checklist" section
open index.html
index.html on the rebased alex-feature branch
oyqox.nlpq az jki wadezad uciy-yiuyize yyahjy

git show main
C4: Updated section styling to use a class
...
diff --git a/index.html b/index.html
     <main>
-      <section>
+      <section class="intro-section">
         <h2>Introduction</h2>
       </section>

-      <section>
+      <section class="checklist-section">
         <h2>Morning Routine Checklist</h2>
...
diff --git a/style.css b/style.css
...
-section {
+.checklist-section {
     background-color: lightcyan;
 }
+
+.intro-section {
+    background-color: lavender;
+}
-      <section>
+      <section class="checklist-section">
         <h2>Evening Routine Checklist</h2>
git add index.html
git commit --amend --no-edit
git show
       </section>
+
+      <section class="checklist-section">
+        <h2>Evening Routine Checklist</h2>
+      </section>
     </main>
open index.html
index.html on the rebased alex-feature branch with the amended commit
idbek.hjgh aj lno duvajaq acaw-qouwuve fwobcs fijn qsi ahifvun febzod

git push -u origin head
git push --set-upstream origin alex-feature  # same as above
...
To ../../checklists.git
 * [new branch]      head -> alex-feature
Branch 'alex-feature' set up to track remote branch 'alex-feature'
from 'origin'.
git fetch
...
From ../../checklists
   7ddf0a8..45874cd  beth-chad-feature -> origin/beth-chad-feature
 * [new branch]      alex-feature      -> origin/alex-feature
git pull
git checkout alex-feature
git log -p main..
git checkout main
git merge alex-feature
git push
git branch -d alex-feature
git push origin --delete alex-feature
open index.html
index.html in the beth-chad-feature branch
ittis.gyrb as zze lehh-jjiz-daizico psugrk

       <section class="checklist-section">
-        <h2>Morning Routine Checklist</h2>
+        <h2>Morning Checklist</h2>
       </section>
git fetch
...
From ../../checklists
   51bdc3c..b021b4e  main       -> origin/main

git checkout main
git pull
git checkout -
Switched to branch 'beth-chad-feature'
git merge main --no-edit
open index.html
Chad’s index.html after merging main into beth-chad-shared
Lkoh’v ojtin.ykdg apbik hanfeqg siez uzwu dizx-xvoj-cvihol

       <section class="checklist-section">
-        <h2>Evening Routine Checklist</h2>
+        <h2>Evening Checklist</h2>
       </section>
git commit -am "C7: Removed Routine from heading"
open index.html

git push
git fetch
...
   45874cd..10c94b0  beth-chad-feature -> origin/beth-chad-feature
   51bdc3c..b021b4e  main              -> origin/main
git checkout main
git pull
git checkout beth-chad-feature

git rebase main
* f252dbe (HEAD -> beth-chad-feature) C7: Removed Routine from heading
* 33d826e C6: Removed "Routine" from heading
* 5bb5fba B6: Added <hr/> in <header>
* 9b63f85 C5: Added <footer> to <body>
* 58ca4b6 B5: Moved <h1> and <p> within <header>
...
git log -p -2
C7: Removed Routine from heading
...
       <section class="checklist-section">
-        <h2>Evening Routine Checklist</h2>
+        <h2>Evening Checklist</h2>
       </section>
...

C6: Removed "Routine" from heading
...
       <section class="checklist-section">
-        <h2>Morning Routine Checklist</h2>
+        <h2>Morning Checklist</h2>
       </section>
...
git rebase -i head~2
pick 0383368 C6: Removed "Routine" from heading
pick 4652fdc C7: Removed Routine from heading
pick 0383368 C6: Removed "Routine" from heading
f 4652fdc C7: Removed Routine from heading
git show
C6: Removed "Routine" from heading
...
       <section class="checklist-section">
-        <h2>Morning Routine Checklist</h2>
+        <h2>Morning Checklist</h2>
       </section>

       <section class="checklist-section">
-        <h2>Evening Routine Checklist</h2>
+        <h2>Evening Checklist</h2>
       </section>
...
git checkout main
git merge beth-chad-feature
git push
git branch -d beth-chad-feature
warning: not deleting branch 'beth-chad-feature' that is not yet merged to
    'refs/remotes/origin/beth-chad-feature', even though it is merged to HEAD.
error: The branch 'beth-chad-feature' is not fully merged.
If you are sure you want to delete it, run 'git branch -D beth-chad-feature'.
git push origin --delete beth-chad-feature
git branch -d beth-chad-feature

Key points

  • In the Feature Branch Workflow, you create a branch any time you want to work on a new feature.
  • You should update your branch periodically with new changes in main.
  • You must update your branch with main before pushing it up for review.
  • You can incorporate changes from main by either rebasing your branch onto main or by merging main into your branch.
  • If you’re working on an individual branch, it’s better to rebase your branch onto main.
  • Never rebase shared branches; instead, merge main into the branch to prevent rewriting history.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now