Chapter 4

Version Control and Release Management with Git

This chapter covers the following topics:

  • Version Control and Git: This section briefly discusses version control for managing code or file changes and how Git is a widely used version control system (VCS). It also discusses Git basics and advanced features for managing code changes from multiple concurrent developers.

  • Git Workflow: This section discusses Git basic workflow agreement, how to manage access to the code, and who contributes and who is trusted to manage the workflow. Basics of branching and forking are also discussed.

  • Git Branching Strategy: This section discusses a strategy for managing the code development and stabilization teams and processes. This is a strategy that all developers must understand and agree upon.

This chapter maps to the first part of the Developing Applications Using Cisco Core Platforms and APIs v1.0 (350-901) Exam Blueprint Section 1.0, “Infrastructure and Automation,” specifically subsections 1.10 and 1.11.

This chapter describes version control, version control systems (VCSs) in general, and then goes on to describe Git as a version control system. The concept of version control is simple and used in every aspect of our lives: documents, applications, operating systems, webpages, standards, frameworks—you get the idea. The code you build for automating and orchestrating your network is no different. We’re confident that you’re not building the code by yourself, and we’re confident you’re not building it in one sitting. You’re collaborating with others and most probably in an agile development process where various releases and sprints are in order. This chapter teaches you how to keep track of the development process.

“Do I Know This Already?” Quiz

The “Do I Know This Already?” quiz allows you to assess whether you should read this entire chapter thoroughly or jump to the “Exam Preparation Tasks” section. If you are in doubt about your answers to these questions or your own assessment of your knowledge of the topics, read the entire chapter. Table 4-1 lists the major headings in this chapter and their corresponding “Do I Know This Already?” quiz questions. You can find the answers in Appendix A, “Answers to the ‘Do I Know This Already?’ Quizzes.”

Table 4-1 “Do I Know This Already?” Section-to-Question Mapping

Foundation Topics Section

Questions

Version Control and Git

1

Git Workflow

2, 3

Git Branching Strategy

4, 5

1. What is version control used to track?

  1. Code changes

  2. Configurations

  3. Releases

  4. All of these answers are correct.

2. What is the difference between Git and GitHub?

  1. There is no difference.

  2. GitHub is used for hosting Git projects.

  3. GitHub has a hub, and Git does not.

  4. GitLab, GitHub, and Git are different names for the same thing.

3. The main benefit of a VCS is your ability to do what?

  1. Manage code for multiple development projects.

  2. Streamline the development cycle or process.

  3. Track and save all changes.

  4. All of these answers are correct.

4. Which scenario is more likely to cause a merge conflict?

  1. Two developers open the same file.

  2. A file gets deleted by one developer while it’s being modified by another developer.

  3. Two merges are performed back-to-back.

  4. All these scenarios are easily handled by Git.

5. Which statements are correct about branching? (Choose two.)

  1. Branching is important only if you plan to merge changes from two independent projects.

  2. A branching strategy needs to define types of branches and all rules governing usage by the developers.

  3. Every developer must understand the strategy and agree to follow it.

  4. Branching strategies must be agreed upon only by development team leads, not all developers.

Foundation Topics

Version Control and Git

When we discussed maintainability and modifiability in the preceding chapter, we started with a statement that is super fit to use here: “Change is constant.” Therefore, a system or methodology for tracking changes to a code, who made them, and for what purpose becomes a very important component of a project. Version control, or simply versioning, can be at all levels of the development process: a module, function, feature, system, or application.

A number of popular systems are in use today, and most of the time the one you use will be the one that your company supports and that your development team is currently using. Git is such a system; it has gained a lot of popularity recently for its ease of use (at least the latest versions) and simplicity, and because it’s open source. In the next few sections, we describe Git and look at some of its basic and advanced features.

Git differentiates itself in being fast and efficient, and also by having the following interesting features:

  • A typical VCS stores deltas, or file changes, over a period of time (delta-based version control), whereas Git stores snapshots of files and the filesystem.

  • Almost all operations are local to your system or computer. All related history is stored locally and can be accessed regardless of whether you’re online or offline.

  • Data in Git is verified for integrity through a checksum algorithm. A checksum is produced before storing a file, and the checksum is used to refer to the file or data.

For more information about Git and how it works, we highly recommend you refer to the free book written by Scott Chacon and Ben Straub and contributed to by the Git developer community: Pro Git, Version 2.1.240. It was used as a reference for this book. You can refer to the book and to online documentation for installing and learning Git.

Git Workflow

When multiple people need to collaborate and contribute to the same Git repository for a project, there needs to be a working agreement on how that work will be done. A team must agree on an operating model for coordinating their contributions to a shared, source-of-truth code repository.

The Git Workflow that a team selects depends on the following:

  1. Shared repo access policies

    • Will all contributors have read-write access to the shared repository?

    • Or will some contributors have read-only access to the shared repository?

  2. Untrusted contributors

    • Are all contributors known up front and trusted with repository read-write access?

    • Or will some contributors be untrusted or from the public?

  3. Novice versus intermediate Git users

    • Will users follow a more complex workflow that is used by the vast majority of open-source projects?

    • Or will they follow a simpler workflow that novice users of Git may easily understand?

The following sections detail the two primary workflows that teams use: the Branch and Pull Workflow and the Fork and Pull Workflow.

Branch and Pull Workflow

The Branch and Pull Workflow is the simpler of the two options for Git workflows. It works best with the following properties:

  • Shared repo access policies: All contributors have read-write access to the shared repository.

  • Trusted contributors: All contributors are known up front and trusted with repository read-write access.

  • Novice versus intermediate Git users: The team requires a simpler workflow that novice users of Git may easily understand.

The Branch and Pull Workflow has the following pros and cons.

Pros
  • This model requires only simple knowledge of Git, only incrementally different from working solo on a Git repository because only a single Git repo is involved.

  • It does not require a contributor to be aware of the concept of forking.

  • Because there are no forks, the user does not need to understand how to manage working with distributed Git repos (that is, synchronizing the same source code among many repos).

Cons
  • This model diverges from the way that the vast majority of open-source software works (most open-source software uses the Fork and Pull Workflow).

  • All code contributors must have read-write access to the shared, source-of-truth repository.

  • This workflow is less safe because all team members have read-write access and are pushing to the same source of truth, allowing the possibility of overwriting each other’s branches, especially shared branches such as the main or master.

  • This model cannot work for untrusted contributors who do not have write access to the shared repository.

Sample Setup

Next, let’s look at a sample setup, followed by the actual Branch and Pull example.

  1. Assume that you have configured your github.com user profile with an SSH key.

    • This allows you to execute remote Git operations such as clone and push using SSH-key authentication.

    • Otherwise, Git defaults to using password authentication, which requires you to frequently type in a username and password.

  2. Assume that bluecodemonks is your team name.

  3. Assume that go-hello-world will be a team collaboration project.

  4. Assume that you have already been added as a read-write contributor to the project. Figure 4-1 shows the go-hello-world project.

Figure 4-1 Branch and Pull: Origin Repository

Sample Branch and Pull Workflow

Note

You cannot follow along with this exercise using this specific repository because you don’t have write access to the repo at https://github.com/bluecodemonks/go-hello-world. This illustrates the limitations of the Branch and Pull Workflow. The counter Fork and Pull Workflow does not have this limitation, however, as you will see in a subsequent exercise.

Step 1. Clone the project repository to your local computer:

$ mkdir ~/Dev
$ cd ~/Dev
$ git clone [email protected]:bluecodemonks/go-hello-
  world.git
Cloning into 'go-hello-world'...
[snipped]

Step 2. You now have a local copy of the project repository on your filesystem, as seen in Figure 4-2, where the local clone of go-hello-world was created.

Figure 4-2 Branch and Pull: Locally Cloned Repo

Step 3. Look around the newly cloned repository:

$ cd ~/Dev/go-hello-world
$ tree
.
├── LICENSE
├── README.md
├── go.mod
└── main.go
0 directories, 4 files

Step 4. Notice that a Git remote repository configuration has already been set up because you cloned from a remote repository.

  • This repository is named origin (by default).

  • It refers to the original URI from which this repo was cloned.

  • Your team’s shared, source-of-truth remote repo is now labeled origin:

$ git remote -v
origin [email protected]:bluecodemonks/go-hello-world.git
(fetch)
origin [email protected]:bluecodemonks/go-hello-world.git
(push)

Step 5. Look at what branch you are currently on and what branches are available.

  • You are on the main branch, denoted by the asterisk (*) character.

  • Your local main branch is at the same commit as the remote origin/main branch. It is set to track the origin/main remote upstream by default (see Figure 4-3). Thus, if you execute commands such as git push without fully qualifying where to push, it assumes the target is the default origin/main remote upstream. To push to a specific git remote and specific branch on that remote, you may fully qualify the target git push <remote>/<branch>.

    Figure 4-3 Branch and Pull: Main Branch Tracking

$ git branch -avv
* main ad0bbc5 [origin/main] Added install and run
instructions
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run
instructions

Step 6. Now it’s time to make a contribution. First, create a local branch to store your local changes. Because you are currently on the main branch, your new branch will be created from main. Example 4-1 shows the CLI commands, and Figure 4-4 illustrates the logical results.

Figure 4-4 Branch and Pull: Creating a Branch

Example 4-1 Creating a Branch

# Check what branch we are on
$ git branch
* main
# Create a new feature-branch from "main" and switch to it
$ git checkout -b update-readme
Switched to a new branch 'update-readme'
# View your branch status
$ git branch -avv
 main ad0bbc5 [origin/main] Added install and run instructions
* update-readme ad0bbc5 Added install and run instructions
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run instructions

Step 7. Now, make some edits to the README.md file. You can enhance the README.md with uninstall instructions:

$ vi README.md
Uninstall
```

$ rm $GOPATH/bin/go-hello-world
```

Step 8. Assess your changes before you stage them.

This step is not required but is extremely good practice to evaluate your changes before you stage them. The steps are described in Example 4-2.

Example 4-2 Branch and Pull: Reviewing Current Changes

$ git status
On branch update-readme
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
no changes added to commit (use "git add" and/or "git commit -a")

$ git diff
diff --git a/README.md b/README.md
index f272b4d..8e86322 100644
--- a/README.md
+++ b/README.md
@@ -11,4 +11,10 @@ Run
 ```
 $ go-hello-world
 Hello World
-```
 No newline at end of file
+```
+
+Uninstall
+
+```
+$ rm $GOPATH/bin/go-hello-world
+```

Step 9. Stage your changes:

$ git add README.md

Step 10. Assess your staged changes to double-check your edits.

This step is not required but is extremely good practice to evaluate your changes before you commit them. The steps to review changes before committing are described in Example 4-3.

Example 4-3 Branch and Pull: Reviewing Staged Changes

$ git diff --cached
diff --git a/README.md b/README.md
index f272b4d..8e86322 100644
--- a/README.md
+++ b/README.md
@@ -11,4 +11,10 @@ Run
 ```
 $ go-hello-world
 Hello World
-```
 No newline at end of file
+```
+
+Uninstall
+
+```
+$ rm $GOPATH/bin/go-hello-world
+```

Step 11. Commit the changes to the local branch:

$ git commit -m "Update README.md with uninstall
instructions"
[update-readme bb63877] Update README.md with uninstall
instructions
 1 file changed, 7 insertions(+), 1 deletion(-)

Step 12. Push a copy of your local branch update-readme to the shared source-of-truth repo. The git push command is illustrated in Example 4-4 and logically represented in Figure 4-5.

Figure 4-5 Branch and Pull: Listing All Branches

  • The source-of-truth repo is named origin in your git remotes:

$ git remote -v
origin [email protected]:bluecodemonks/go-hello-world.git
(fetch)
origin [email protected]:bluecodemonks/go-hello-world.git
(push)
  • Notice that you are currently on the update-readme local branch and that the origin git remote has no such branch:

$ git branch -avv
 main ad0bbc5 [origin/main] Added install and run
instructions
* update-readme 8144024 Update README.md with uninstall
instructions
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run
 instructions
  • Thus, you must push the current branch to the origin remote, specifying a fully qualified branch name in the format <remote> <branch>.

Example 4-4 Branch and Pull: Pushing a Branch to the Origin Repo

$ git push origin update-readme
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (1/1), done.
Writing objects: 100% (3/3), 367 bytes | 367.00 KiB/s, done.
Total 3 (delta 2), reused 2 (delta 2), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
Remote:
remote: Create a pull request for 'update-readme' on GitHub by visiting:
remote: https://github.com/bluecodemonks/go-hello-world/pull/new/update-readme
remote:
To github.com:bluecodemonks/go-hello-world.git
 * [new branch] update-readme -> update-readme
  • Now, verify that the remote origin has a new branch named updated-readme:

$ git branch -avv
 main ad0bbc5 [origin/main] Added install and run
instructions
* update-readme bb63877 Update README.md with uninstall
instructions
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run
instructions
 remotes/origin/update-readme bb63877 Update README.md
with uninstall instructions

Step 13. Initiate a pull request (PR) through the repo on the GitHub UI by clicking the Compare & Pull Request button shown in Figure 4-6.

Figure 4-6 Branch and Pull: GitHub Origin Repo Page

You are taken to the Open a Pull Request page (as shown in Figure 4-7).

Figure 4-7 Branch and Pull: Opening a Pull Request

  • Notice that you are asking to merge the update-readme branch into the main branch.

  • This is your opportunity to provide a name for the pull request, as well as add additional comments if necessary.

Step 14. Scroll down and inspect the proposed code changes. In Figure 4-8, notice the changes in the lower window, shown as “showing 1 changed file with 7 additions and 1 deletion.”

Figure 4-8 Branch and Pull: Reviewing Pull Request Changes Before Submitting

  • If the code changes are not what you expected, you may make additional commits in your local update-readme branch and then push the additional commits to the origin/update-readme branch, which will then automatically update the pull request.

Step 15. Click the Create Pull Request button. Figure 4-9 clearly illustrates the pull request, and Figure 4-10 shows that the pull request is complete and ready for review.

Figure 4-9 Branch and Pull: Submitting Pull Request

Figure 4-10 Branch and Pull: Submit Pull Request Complete

Step 16. Get your PR code reviewed by a friend or colleague:

  • The code reviewer should signal that the pull request is in an acceptable/mergeable state by providing an approval signal or comment (shown as thumbs up in Figure 4-11).

    Figure 4-11 Branch and Pull: Code Review Approval

  • If the code reviewer requests changes, the reviewer can comment on the code, and you may fix the identified issues by making additional commits in your local update-readme branch and then pushing the additional commits to the origin/update-readme branch, which then automatically updates the PR.

Step 17. Now that your pull request has been code reviewed and approved, you may merge your PR by clicking the Merge Pull Request button. Figure 4-12 shows the approval.

Figure 4-12 Branch and Pull: Approved for Merge

  • Subsequently, confirm the merge, as shown in Figure 4-13.

Figure 4-13 Branch and Pull: Confirm Merge

Step 18. The PR will be fully merged after the Confirm button is clicked. For the purposes of maintaining this sample repository, do not merge this PR; instead, leave it in the open state for people to inspect.

Step 19. Because you pushed your branch update-readme to a shared repository, common courtesy is to delete your branch from the shared repository.

  • Note that this step is unnecessary in the Fork and Pull Workflow.

Fork and Pull Workflow

The Fork and Pull Workflow is the more complex of the two options for Git workflows, but it works in all use cases. In addition, it is the most popular Git workflow in the open-source and commercial worlds because it enables contributions from untrusted contributors without read-write access to the shared, source-of-truth repo.

It works when

  • Shared repo access policies: Contributors have a minimal read-only access to the shared repository.

  • Untrusted contributors: Unknown, untrusted, or public contributors.

  • Novice versus intermediate Git users: The team is capable of following a more complex workflow, especially if they are already familiar with the open-source model.

This Fork and Pull Workflow has the following pros and cons.

Pros
  • This model matches the workflow of the vast majority of open-source software.

  • All code contributors follow the same workflow:

    • Whether a contributor is a complete stranger

    • Whether a contributor has read-only or read-write access to the shared, source-of-truth repository

  • This workflow is safer because team members with write access by default push changes to their own forks before PR (instead of to a shared repository).

  • This model can work for untrusted contributors who do not have write access to the shared repository.

Cons
  • This model requires a higher competence of Git, beyond working in a solo repository.

  • It requires a contributor to be aware of the concept of forking.

Sample Setup

Let’s look at a sample setup, followed immediately by the actual Fork and Pull Workflow.

Step 1. Assume that you have configured your github.com user profile with an SSH key.

  • This allows you to execute remote Git operations such as clone and push using SSH-key authentication.

  • Otherwise, Git defaults to using password authentication, which requires you to frequently type in a username and password.

Step 2. Assume that bluecodemonks is a GitHub organization that has a code repository that you would like to contribute to.

Step 3. Assume that you would like to contribute to the go-hello-world repository.

Step 4. Assume that you have read-only access to this project, which has been enabled publicly readable by the project maintainers so that anyone on the Internet may view the source code. Figure 4-14 shows the bluecodemonks organization’s project called go-hello-world.

Figure 4-14 Fork and Pull: Origin Repo

  • This organization might not know you, but you are still able to contribute!

Sample Fork and Pull Workflow

Step 1. From the shared, source-of-truth repo, fork the project repository to your personal GitHub organization (shown in Figure 4-15).

Figure 4-15 Fork and Pull: GitHub Origin Repository

Step 2. Go to your forked repository in your personal GitHub organization:

Step 3. Your fork is now tracking the shared, source-of-truth team repo.

  • A fork is essentially a clone of the original GitHub repo but is stored in a different GitHub organization than the original rather than your local disk. GitHub tracks the parent of the fork, to set defaults such as default targets for pull request initiation. Notice the difference between the original and the clone (fork) in the logical representation shown in Figure 4-17.

Figure 4-17 Fork and Pull: Forked Personal Repo

Step 4. Clone the project repository to your local computer:

$ mkdir ~/Dev
$ cd ~/Dev
$ git clone [email protected]:dcwangmit01/go-hello-world.git
Cloning into 'go-hello-world'...
[snipped]

Step 5. You now have a local copy of the project repository on your filesystem. The local copy is shown in Figure 4-18.

Figure 4-18 Fork and Pull: Locally Cloned from Fork of Origin Repo

Step 6. Look around the newly cloned repository:

$ cd ~/Dev/go-hello-world
$ tree
.
├── LICENSE
├── README.md
├── go.mod
└── main.go
0 directories, 4 files

Step 7. Notice that a Git remote repository configuration has already been set up because you cloned from a remote repository.

  • This repository is named origin (by default).

  • It refers to the original URI from which this repo was cloned, which is the personal repository fork, instead of the shared, source-of-truth bluecodemonks.

$ git remote -v
origin [email protected]:dcwangmit01/go-hello-world.git
(fetch)
origin [email protected]:dcwangmit01/go-hello-world.git
(push)

Step 8. Add an additional Git remote repository configuration for the original shared, source-of-truth repository.

  • Explicitly name the remote repository upstream, as in the original repo that has been forked.

$ git remote add upstream [email protected]:bluecodemonks/
go-hello-world.git
$ git remote -v
origin [email protected]:dcwangmit01/go-hello-world.git
(fetch)
origin [email protected]:dcwangmit01/go-hello-world.git
(push)
upstream [email protected]:bluecodemonks/go-hello-world.git
(fetch)
upstream [email protected]:bluecodemonks/go-hello-world.git
(push)
  • Note that you may name these Git remotes however you choose. An alternate configuration may be to name the original shared, source-of-truth forked repository origin and then name any other remote to be the name of the GitHub organization. This helps if you need to access the personal forks of people you are collaborating with. Your configuration might look like this:

$ git remote -v
origin [email protected]:bluecodemonks/go-hello-world.git
(fetch)
origin [email protected]:bluecodemonks/go-hello-world.git
(push)
jack [email protected]:jack/go-hello-world.git (fetch)
jack [email protected]:jack/go-hello-world.git (push)
jill [email protected]:jill/go-hello-world.git (fetch)
jill [email protected]:jill/go-hello-world.git (push)
you [email protected]:you/go-hello-world.git (fetch)
you [email protected]:you/go-hello-world.git (push)
  • The rest of this example assumes the more common naming convention that the original, shared source-of-truth repository is named upstream.

Step 9. Look at what branch you are currently on and what branches are available.

  • You are on the main branch, denoted by the asterisk (*) character.

  • Your local main branch is at the same commit as the remote origin/main branch. It is set to track the origin/main remote upstream by default. Thus, if you execute commands such as git push without fully qualifying where to push, it assumes the target is the default origin/main remote upstream. To push to a specific Git remote and specific branch on that remote, you may fully qualify the target git push <remote>/<branch>. Note the logical representation in Figure 4-19.

    Figure 4-19 Fork and Pull: Main Branch Tracking

$ git branch -avv
* main ad0bbc5 [origin/main] Added install and run
instructions
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run
instructions
 remotes/origin/update-readme bb63877 Update README.md
with uninstall instructions

Step 10. Now it’s time to make a contribution. First, create a local branch to store your local changes. Because you are currently on the main branch, the new branch is created from main. The steps are illustrated in Example 4-5 and logically represented in Figure 4-20.

Example 4-5 Fork and Pull: Creating a Branch

# Check what branch we are on
$ git branch
* main

# Create a new feature-branch from "main" and switch to it
$ git checkout -b update-readme-2
Switched to a new branch 'update-readme-2'

# View your branch status
$ git branch -avv
 main ad0bbc5 [origin/main] Added install and run instructions
* update-readme-2 ad0bbc5 Added install and run instructions
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run instructions
 remotes/origin/update-readme bb63877 Update README.md with uninstall instructions

Figure 4-20 Fork and Pull: Creating a Branch

Step 11. Now make some edits to the README.md file. You’re going to enhance the README.md with details:

$ vi README.md
This is an example repo.

Step 12. Assess your changes before you stage them.

The step represented in Example 4-6 is not required but is extremely good practice to evaluate your changes before you stage them.

Example 4-6 Fork and Pull: Reviewing Current Changes

$ git status
On branch update-readme-2
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

no changes added to commit (use "git add" and/or "git commit -a")

$ git diff
diff --git a/README.md b/README.md
index f272b4d..567f23b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
 # go-hello-world

+This is an example repo.
+
 Install

 ```

Step 13. Stage your changes:

$ git add README.md

Step 14. Assess your staged changes to double-check your edits.

This step, illustrated in Example 4-7, is not required but is extremely good practice to evaluate your changes before you commit them.

$ git diff --cached

Example 4-7 Fork and Pull: Reviewing Staged Changes

diff --git a/README.md b/README.md
index f272b4d..567f23b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
 # go-hello-world

+This is an example repo.
+
 Install

 ```

Step 15. Commit the changes to the local branch:

$ git commit -m "Update README.md with details"
[update-readme-2 de7b443] Update README.md with details
 1 file changed, 2 insertions(+)

Step 16. Push a copy of your local branch update-readme-2 to your personal fork repo (instead of the shared source-of-truth repo).

  • The personal fork repo is named origin in your Git remotes:

$ git remote -v
origin [email protected]:dcwangmit01/go-hello-world.git
(fetch)
origin [email protected]:dcwangmit01/go-hello-world.git
(push)
upstream [email protected]:bluecodemonks/go-hello-world.git
(fetch)
upstream [email protected]:bluecodemonks/go-hello-world.git
(push)
  • Notice that you are currently on the update-readme-2 local branch and that the origin Git remote has no such branch:

$ git branch -avv
 main ad0bbc5 [origin/main] Added install and run
instructions
* update-readme-2 de7b443 Update README.md with details
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run
instructions
 remotes/origin/update-readme bb63877 Update README.md
with uninstall instructions
  • Thus, you must push the current branch to the origin remote, specifying a fully qualified branch name in the format <remote> <branch>.

  • The configuration steps are shown in Example 4-8 and illustrated in Figure 4-21.

    Figure 4-21 Fork and Pull: Listing All Branches

Example 4-8 Fork and Pull: Pushing a Branch to Forked Repo

$ git push origin update-readme-2
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 380 bytes | 380.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
Remote:
remote: Create a pull request for ‘update-readme-2’ on GitHub by visiting:
remote: https://github.com/dcwangmit01/go-hello-world/pull/new/update-readme-2
remote:
To github.com:dcwangmit01/go-hello-world.git
 * [new branch] update-readme-2 -> update-readme-2
  • Now verify that the remote origin has a new branch named updated-readme:

$ git branch -avv
 main ad0bbc5 [origin/main] Added install and run
instructions
* update-readme-2 de7b443 Update README.md with details
 remotes/origin/HEAD -> origin/main
 remotes/origin/main ad0bbc5 Added install and run
instructions
 remotes/origin/update-readme bb63877 Update README.md
with uninstall instructions
 remotes/origin/update-readme-2 de7b443 Update README.md
with details

Step 17. Now initiate a pull request from your personal fork to the shared, source-of-truth repo on the GitHub UI by clicking the Compare & Pull Request button. You may initiate this pull request from either your personal fork or the shared, source-of-truth repo. In the example, shown here in Figure 4-22, the latter is chosen.

Figure 4-22 Fork and Pull: GitHub Origin Repo Page

Step 18. You are taken to the Open a Pull Request page.

  • Notice that you are asking to merge the update-readme-2 branch into the main branch.

  • This is your opportunity to provide a name for the pull request, as well as add additional comments if necessary.

  • Figure 4-23 shows the Open a Pull Request page and the text box for adding your comments.

Figure 4-23 Fork and Pull: Opening a Pull Request

Step 19. Scroll down and inspect the proposed code changes. Figure 4-24, which is a continuation of Figure 4-23, shows the proposed code changes for review before submitting.

Figure 4-24 Fork and Pull: Reviewing Pull Request Changes Before Submitting

  • If the code changes are not what you expected, you may make additional commits in your local update-readme branch and then push the additional commits to the origin/update-readme branch, which then automatically updates the PR.

Step 20. Click the Create Pull Request button. Figure 4-25 shows the Create pull request step, and it is immediately followed by Figure 4-26 showing the pull request complete.

Figure 4-25 Fork and Pull: Submitting Pull Request

Figure 4-26 Fork and Pull: Submit Pull Request Complete

Step 21. Get your PR code reviewed by a friend or colleague.

  • The code reviewer should signal that the pull request is in an acceptable/mergeable state by providing an approval signal or comment. See Figure 4-27 for more details.

  • If the code reviewer requests changes, the reviewer can comment on the code, and you may fix the identified issues by making additional commits in your local update-readme branch and then pushing the additional commits to the origin/update-readme branch, which then automatically updates the PR.

Figure 4-27 Fork and Pull: Code Review Approval

Step 22. Now that your pull request has been code reviewed and approved, you may merge your PR by clicking the Merge Pull Request button. Figure 4-28 shows that the approval has been obtained (for example, 1 approval), and now it is ready for Merge.

Figure 4-28 Fork and Pull: Approved for Merge

  • Subsequently, confirm the merge, as shown in Figure 4-29.

    Figure 4-29 Fork and Pull: Confirm Merge

Step 23. Now the pull request will be fully merged after the Confirm button is clicked. For the purposes of maintaining this sample repository, do not merge this PR; instead, leave it in the open state for people to inspect.

Git Branching Strategy

Branching is easy to understand and is a powerful tool when dealing with larger projects involving multiple developers. However, all powerful tools can be useless if the team does not agree on a common workflow and a branching strategy. The following sections discuss the most common branching strategies and how to use them.

What Is a Branching Strategy?

A branching strategy is a team working agreement that enables the management of

  • Developing code: Destabilizes code because development introduces code changes

  • Stabilizing code: Stabilizes code through reducing the rate of code changes

The need for code development for new features versus stabilizing code for release is a constant push and pull. Thus, a team needs a working agreement on managing this process.

The Most Important Factor When Selecting a Git Branching Strategy

When you’re deciding on a branching strategy, the most important question that influences the outcome is, Do you trust your automated tests?

If your automated tests are comprehensive enough where a pass result on its own is trusted evidence that the code is deployable to production, your team is a shining example of modern software development.

Popular Git Branching Strategies

If you do a web search on Git branching strategies, you’ll find a large collection of documented strategies. The most popular ones are as follows:

When to Use GitHub Flow

GitHub Flow is the recommended branch strategy for all software projects that are disciplined and adhere to comprehensive automated test coverage. New software projects should always start with this modern-day approach.

If you answered “yes” to the question “Do you trust your automated tests?” it enables a lot of good things:

  1. You are able to keep a stable main branch because tests can block the PR merge.

  2. You are able to release to production several times a day.

  3. You can tag versions of your release directly from the main branch.

  4. You have no need for release branches to stabilize your product.

  5. You have no need for code freezes to stabilize your product.

  6. You have no dependencies on manual quality assurance (QA) to stabilize your product.

Here’s a visualization of the GitHub Flow model. Notice that a single, linear main branch exists with only feature branches and without the existence of release branches. This example (shown in Figure 4-30) is the simplest of the Git branching strategies; it keeps a single main branch stable.

Figure 4-30 GitHub Flow Branch Visualization

If you’re not able to trust your automated tests because they are not comprehensive, then GitHub Flow does not work. Instead, use a different model called Git Flow.

Most of the open-source world uses GitHub Flow.

When to Use Git Flow

Git Flow is the recommended branch strategy for software projects that are not disciplined with comprehensive automated test coverage. Typically, legacy software development projects that rely on days, weeks, or months of manual QA testing should follow the Git Flow branch strategy. Git Flow uses release branches to allow development and quality assurance teams to stabilize code for a release, while allowing code development to proceed on the main branch.

Git Flow is not recommended as a first choice for branch strategy, unless your project falls into this legacy category. In fact, the original author of Git Flow now recommends GitHub Flow. You can read the original article at https://nvie.com/posts/a-successful-git-branching-model/.

If you answered “no” to the question “Do you trust your automated tests?” your project may have a lot of legacy qualities:

  1. You are unable to keep a stable main branch because your automated tests are not comprehensive enough to block PR merges based on test results.

  2. You are unable to release to production several times a day.

  3. You cannot tag versions of your release directly from the main branch because main is not kept stable.

  4. You must use release branches to stabilize your product, and you tag your releases off the release branches.

  5. You need code freezes to stabilize your product.

  6. You have dependencies on manual QA to stabilize your product.

Figure 4-31 shows a visualization of the Git Flow model.

Figure 4-31 Git Flow Branch Visualization

The Git Flow branching strategy allows teams to stabilize code in release branches that are code-frozen for bug fixes only. In addition, development may continue to move forward and allow destabilized code to continue to be merged into the develop branch. The main branch would only receive merges from stabilized release branches.

When to Use GitLab Flow

GitLab Flow is a Git branching strategy that is centered around a main branch as the base branch and enables maintaining a separate branch per environment (develop, staging, product). As changes occur in the environment branches, they may be cherry-picked back into the main branch.

This branching strategy can increase complexity and its procedural impact should be carefully reviewed if needed for your use cases. Read more at https://docs.gitlab.com/ee/topics/gitlab_flow.html.

Recommended GitHub Settings

Shared, source-of-truth GitHub repositories should be configured for team access and code reviews. These settings are available via the repo settings page. In this example, the settings page, which is found at https://github.com/bluecodemonks/go-hello-world/settings, is accessible only by repository owners.

Configuring the PR Merge Button

Merge button settings are found under Options > Merge Button. To keep a clean Git commit history, we recommend that you rebase merging and thus disable the other options (see Figure 4-32).

Figure 4-32 GitHub Repo Merge Button Settings

Rebase merging enables a team to keep a clean, linear Git history.

Configuring a Branch Protection Rule to Require Code Reviews

In GitHub, a branch protection rule may be used to disallow contributors to push directly to a shared branch without certain prerequisites, such as code reviews. Configuration is done at the page shown in Figure 4-33.

Figure 4-33 GitHub Repo Branch Protection Rules

From the main page shown in the figure, an administrator may add a branch protection rule. A common practice is to add a branch protection rule for the main branch.

The main shared branch is often a branch that needs protection, affecting important practices such as

  • Disabling the ability to directly push to a branch without a code review

  • Requiring one or more code review approvals before enabling PR merges

  • Enforcing a linear commit history

The settings are shown in Figure 4-34.

Figure 4-34 GitHub Repo Branch Protection Rule

In this chapter we provided you with frequently used commands, techniques, and workflows for version control. As your projects grow in size and the number of developers and testers, your version control system also grows in complexity. Depending on your organization, we highly recommend you take a deeper look at Git through practice and use the Pro Git book mentioned at the beginning of this chapter.

Exam Preparation Tasks

As mentioned in the section “How to Use This Book” in the Introduction, you have a couple of choices for exam preparation: the exercises here, Chapter 17, “Final Preparation,” and the exam simulation questions on the companion website.

Review All Key Topics

Review the most important topics in this chapter, noted with the Key Topic icon in the outer margin of the page. Table 4-2 lists a reference of these key topics and the page numbers on which each is found.

Table 4-2 Key Topics for Chapter 4

Key Topic Element

Description

Page Number

Step list

Sample branch and pull workflow

90

Section

Fork and Pull Workflow

104

List

Popular Git branching strategies

122

Section

When to Use Git Flow

123

Section

Recommended GitHub Settings

125

Complete Tables and Lists from Memory

There are no memory tables or lists in this chapter.

Define Key Terms

Define the following key terms from this chapter and check your answers in the glossary:

version control

version control system

References

URL

QR Code

ProGit: Everything You Need to Know About Git

https://github.com/progit/progit2

github.com

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.114.221