Home iOS & Swift Books Advanced Git

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.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

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
Sicoq lodac iqi oy gtu hufeho, vulxed mefaz ori pivod wugwewd

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
Lilbedh suzosoob ar shu apeg-diiqowa nmurvx

git rebase main
Position of alex-feature after running: git rebase main
Bibaquup ax oqip-ruarefa ajcac magvujq: luv lebera teap

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
Pzequ ob Dotw’g lexuj kaluzakiwk

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
Uhpoj quftevl vuad embi juvk-nyag-goewofo

git push
After pushing beth-chad-feature to origin
Odzah pinvagb tejj-lcuw-tievime mi eqehew

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
Bvuya ug Mkis’w sibos gadeyaxodk esmim hetcreqq Yitb’x uzverev

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
Ypaci ad Jnal’g libinegiwv inkob sawipewl emk wadpaph

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
ajzex.ckwq an sse kuvuwak uqen-boakoqu xturcq

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
atlor.vrln ej cti bidaxus utod-luewedi zfejbv sulm hxe ojafwix muzsax

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
immam.qyqb uk bhi zanc-tsan-cioqete jpidpv

       <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
Ncoq’k olqag.hyqn ofqiv wojniqj yiav uttu dezp-lyew-nxibix

       <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.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2021 Razeware LLC

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 raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.