Git Branch
A branch
in git
is a line of development within a repository. Git allows many branches and thus different lines of development within a repository. By default, we have the master branch.
A few years back, the default branch for GitHub was renamed “main”: https://github.com/github/renaming. We will see both in the field.
There are many reasons for branching; there are no hard-set rules about when to branch or work on the master/main branch directly. Most of the time, we create a branch when there is a bug fix, a customer software release, or a development phase. In our example, let us create a branch that represents development, appropriately named the dev
branch:
$ git branch dev
$ git branch
dev
* master
Notice we need to specifically move into the dev branch
after creation. We do that with checkout
:
$ git checkout dev
Switched to branch 'dev'
$ git branch
* dev
master
Let’s add a second file to the dev
branch:
$ echo "my second file" > mySecondFile.txt
$ git add mySecondFile.txt
$ git commit -m "added mySecondFile.txt to dev branch"
[dev a537bdc] added mySecondFile.txt to dev branch
1 file changed, 1 insertion(+)
create mode 100644 mySecondFile.txt
We can go back to the master
branch and verify that the two lines of development are separate. Note that when we switch to the master branch, there is only one file in the directory:
$ git branch
* dev
master
$ git checkout master
Switched to branch 'master'
$ ls
myFile.txt
$ git checkout dev
Switched to branch 'dev'
$ ls
myFile.txt mySecondFile.txt
To have the contents in the dev
branch be written into the master
branch, we will need to merge
them:
$ git branch
* dev
master
$ git checkout master
Switched to branch 'master'
$ git merge dev master
Updating ff7dc1a..a537bdc
Fast-forward
mySecondFile.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 mySecondFile.txt
$ git branch
dev
* master
$ ls
myFile.txt mySecondFile.txt
We can use git rm
to remove a file. To see how it works, let’s create a third file and remove it:
$ touch myThirdFile.txt
$ git add myThirdFile.txt
$ git commit -m "adding myThirdFile.txt"
[master 169a203] adding myThirdFile.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 myThirdFile.txt
$ ls
myFile.txt mySecondFile.txt myThirdFile.txt
$ git rm myThirdFile.txt
rm 'myThirdFile.txt'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: myThirdFile.txt
$ git commit -m "deleted myThirdFile.txt"
[master 1b24b4e] deleted myThirdFile.txt
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 myThirdFile.txt
We will be able to see the last two changes in the log:
$ git log
commit 1b24b4e95eb0c01cc9a7124dc6ac1ea37d44d51a (HEAD -> master)
Author: Eric Chou <echou@yahoo.com>
Date: Fri Nov 8 10:02:45 2019 -0800
deleted myThirdFile.txt
commit 169a2034fb9844889f5130f0e42bf9c9b7c08b05
Author: Eric Chou <echou@yahoo.com>
Date: Fri Nov 8 10:00:56 2019 -0800
adding myThirdFile.txt
We have gone through most of the basic operations we would use for Git. Let’s look at how to use GitHub to share our repository.
GitHub Example
In this example, we will use GitHub as the centralized location to synchronize our local repository and share it with other users.
We will create a repository on GitHub. GitHub has always been free for creating public open-source repositories. Starting in January 2019, it also offers unlimited free private repositories. In this case, we will create a private repository and add the license and .gitignore
file:
Figure 14.1: Creating a private repository in GitHub
Once the repository is created, we can find the URL for it:
Figure 14.2: GitHub repository URL
We will use this URL to create a remote target, which we will use as a “source of truth” for our project. We will name the remote target gitHubRepo
:
$ git remote add gitHubRepo https://github.com/ericchou1/TestRepo.git
$ git remote -v
gitHubRepo https://github.com/ericchou1/TestRepo.git (fetch)
gitHubRepo https://github.com/ericchou1/TestRepo.git (push)
Since we chose to create README.md
and LICENSE
files during creation, the remote repository and local repository are not the same.
GitHub switched to a Personal Access Token (PAT) as the term to be entered as a password a few years ago: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token. To generate a token, click on the profile logo -> Settings -> Developer settings -> Personal Access Tokens. We need to use this token as our password when prompted in the command line.
If we were to push local changes to the new GitHub repository, we would receive the following error (remember to change the branch name to main if that is your default branch):
$ git push gitHubRepo master
Username for 'https://github.com': <skip>
Password for 'https://echou@yahoo.com@github.com': <remember to use your personal access token>
To https://github.com/ericchou1/TestRepo.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'https://github.com/ericchou1/TestRepo.git'
We will go ahead and use git pull
to get the new files from GitHub:
$ git pull gitHubRepo master
Username for 'https://github.com': <skip>
Password for 'https://<username>@github.com': <personal access token>
From https://github.com/ericchou1/TestRepo
* branch master -> FETCH_HEAD
Merge made by the 'recursive' strategy.
.gitignore | 104
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE | 21 +++++++++++++
README.md | 2 ++
3 files changed, 127 insertions(+)
create mode 100644 .gitignore
create mode 100644 LICENSE
create mode 100644 README.md
Now we will be able to push
the contents over to GitHub:
$ git push gitHubRepo master
Username for 'https://github.com': <username>
Password for 'https://<username>@github.com': <personal access token>
Counting objects: 15, done.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (15/15), 1.51 KiB | 0 bytes/s, done. Total 15 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/ericchou1/TestRepo.git a001b81..0aa362a master -> master
We can verify the content of the GitHub repository on the web page:
Figure 14.3: GitHub repository
Now another user can simply make a copy, or clone
, of the repository:
[This is operated from another host]
$ cd /tmp
$ git clone https://github.com/ericchou1/TestRepo.git
Cloning into 'TestRepo'...
remote: Counting objects: 20, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 20 (delta 2), reused 15 (delta 1), pack-reused 0
Unpacking objects: 100% (20/20), done.
$ cd TestRepo/
$ ls
LICENSE myFile.txt
README.md mySecondFile.txt
This copied repository will be the exact copy of my original repository, including all the commit history:
$ git log
commit 0aa362a47782e7714ca946ba852f395083116ce5 (HEAD -> master, origin/master, origin/HEAD)
Merge: bc078a9 a001b81
Author: Eric Chou <skip>
Date: Fri Jul 20 14:18:58 2018 -0700
Merge branch 'master' of https://github.com/ericchou1/TestRepo
commit a001b816bb75c63237cbc93067dffcc573c05aa2
Author: Eric Chou <skip>
Date: Fri Jul 20 14:16:30 2018 -0700
Initial commit
...
I can also invite another person as a collaborator for the project under the repository settings:
Figure 14.4: Repository invite
In the next example, we will see how we can fork a repository and perform a pull request for a repository we do not maintain.
Collaborating with Pull Requests
As mentioned, Git supports collaboration between developers for a single project. We will look at how it is done when the code is hosted on GitHub.
In this case, we will use the GitHub repository for the second edition of this book from Packt’s GitHub public repository. I will use a different GitHub handle, so I appear as a non-administrative user. I will click on the Fork button to make a copy of the repository in my account:
Figure 14.5: Git Fork button
It will take a few seconds to make a copy:
Figure 14.6: Git Fork in progress
After it is forked, we will have a copy of the repository in our account:
Figure 14.7: Git Fork
We can follow the same steps we used to modify the files. In this case, I will make some changes to the README.md
file. After the change is made, I can click on the New pull request button to create a pull request:
Figure 14.8: Pull request
When making a pull request, we should fill in as much information as possible to provide justifications for making the change:
Figure 14.9: Pull request details
The repository maintainer will receive a notification of the pull request; if accepted, the change will make its way to the original repository:
Figure 14.10: Pull request record
GitHub provides an excellent platform for collaboration with other developers; this is quickly becoming the de facto development choice for many large, open-source projects. Since Git and GitHub are used extensively in many projects, a natural next step would be to automate the processes we have seen in this section. In the following section, let’s look at how we can use Git with Python.