1. Practice with GitHub Desktop on a local repository
To do this exercise you will need to install and setup GitHub Desktop. Follow the instructions here.
In this exercise you will initialize a git repository on your computer and explore various git commands with it.
I. Initializing and adding files
If it’s not already open, open GitHub Desktop.
If this is your first time using GitHub Desktop you should see a screen with “Let’s get started!” at the top:
Click the button titled “Create a New Repository on your Local Drive…”
In the Create a New Repository window, enter
test-git-repo
in the “Name” field, then click “Create Repository”. You do not need to fill out any of the other fields.NoteBy default this will create a local repository in your Documents/GitHub folder. You can change where the repo is located by clicking “Choose”. For this tutorial, let’s stick with the default.
You will see a window that has “No local changes” at the top:
In the upper left you will see “Current repository” with “test-git-repo” underneath it, indicating that you are currently looking at your test-git-repo. This is how you will interact with your new repository!
Note that your repository is a folder on your computer, just like any others. You can see this if you click on the button labelled “Show in Explorer” (on Windows) / “Show in Finder” (on a Mac). At the moment, there are no files in your repository, although there is a hidden folder called
.git
and a hidden file called.gitattributes
. You never touch these files; they are whatgit
use to keep track of the contents of this folder. These are what make this folder a repository.TipA local Git repository is a folder on your computer that you have told the application
git
to keep track of. Any folder can be made into a git repository!Let’s add some files to your new repository for git to track. In the following steps, we’ll pretend that we’re a writer working on a script for a new movie. We’re going to use a simple text editor to create a file called
story.txt
. To do that:- If you’re on Windows:
- Open Notepad. This will open a new untitled file.
- Click File -> Save As…
- Navigate to your repository’s directory. If you kept the default path when creating the repository, this should be
PC > Documents > GitHub > test-git-repo
. If you’re not certain, you can verify by clicking on the “Show in Explorer” button in GitHub Desktop. - In the “File name” field enter
story.txt
then click “Save”.
- If you’re on MacOS:
- Open TextEdit and click “New Document”. This will open a new untitled file.
- Select Format -> “Make Plain Text”. (We need to do this to get the desired file extension.)
- Click File -> Save…
- In the “Save As” field type
story.txt
. - In the “Where” field navigate to your repository’s directory. If you kept the default path when creating the repository, this should be
Documents/GitHub/test-git-repo
. If you’re not certain, you can verify by clicking on the “Show in Finder” button in GitHub Desktop. - Click “Save”.
- If you’re on Windows:
Now let’s write our story! Use your text editor to add following to
story.txt
:Once upon a time, in a land far, far away...
WarningType the lines in exactly as they appear above: add a new line after the first “far,”. For reasons that will become clear below, it’s important that the “far away…” is on a separate line.
Save your changes by clicking File -> Save, or by using the keyboard shortcut Ctrl+S (on Windows) / ⌘+S (on Mac).
Now go back to GitHub Desktop. You’ll notice that it has changed from “No local changes” to showing a “Changes” tab with
story.txt
listed with its contents:git
knows you have a file in the directory calledstory.txt
, but it isn’t tracking it yet!Let’s tell
git
to start trackingstory.txt
by making a commit. If it isn’t already, click the box next to “1 changed file”. When you do, you’ll notice that the “Summary (required)” box automatically changes to “Create story.txt”:The summary box and the optional “Description” box below constitute the commit message. This is text that will be added to the commit describing what was done. In this case, GitHub Desktop automatically provides a default message of “Create story.txt”. That’s a good description of what we’ve done, so let’s keep it.
Now click the “Commit 1 file to main” button. When you do, the window will automatically change back to “No local changes”. Congratulations, you’ve made your first
git
commit!What happens when you commit changes?A commit creates a snapshot of the files you committed. Every commit has a commit message, an author, and a unique hash identifying that change. Git keeps a history of all commits made in a repository. From now on, you can go back and view the previous state of a file at different commit points. This is known as version control.
You can view the history of your commits by clicking on the “History” tab:
In this case, there are two commits: an initial commit that was created by GitHub Desktop when the repository was created, and the commit you just made to create
story.txt
.
II. Making changes to files
You’re not happy with your story opening. You don’t want to write fairy tales, you want to write Sci-fi! Go back to your text editor
story.txt
and change the lineOnce upon a time, in a land far,
toA long time ago in a galaxy far,
so that your file now reads:A long time ago in a galaxy far, far away...
Much better. Save the changes to the file.
Go back to GitHub Desktop. Notice that a yellow box with a dot has appeared next to
story.txt
. If you click on story, you should now see a diff that shows what lines have changed instory.txt
:Those pesky .DS_Store files on MacOSAt some point Mac users will notice a file called
.DS_Store
appears in their repo, as it did for me in the screen shot above. This is a hidden file that MacOS automatically creates in every folder for indexing purposes. Do not commit this file to your repository! It’s not something you want to track. For now, just ignore it. Below we provide instructions on how to permanently ignore files like these in your repository.Windows users: carry on.
The yellow box next to
story.txt
means that git recognizes thatstory.txt
has changed, but your changes have not been committed yet. If you go to the History tab, you’ll see that there are still only two commits. If you click on the “Create story.txt” commit, it will show the previous state of the file.Saving is not committing!Simply saving changes to a file will not result in a new snapshot of it! To tell Git to create a snapshot for preservation you have to create a commit. If you make further changes to your file without committing in between, the intermediate changes will not be tracked.
Let’s commit your changes so you don’t lose them! Click the check box next to
story.txt
. When you do, GitHub Desktop will automatically change the summary to “Update story.txt”. That is a description of what we did, but it’s not very informative. Let’s give a more descriptive summary. Change the summary to “Change opening”, then click “Commit 1 file to main”:You’ll now see 2 commits in your history.
Adding files to .gitignore
It frequently happens that you can have files in your repository that you don’t want Git to track. This can be things like temporary build files, or system files like the .DS_Store
on Macs. If you don’t explicitly commit a new file (by clicking the check mark next to it and hitting the commit button), then files won’t be tracked. However, trying to avoid clicking these files can be tedious and error prone. You’ll also get warnings about changes every time you switch branches (below).
We can tell Git to ignore certain files. Here, we’ll tell it to ignore the .DS_Store
file created by MacOS.
Windows users will not have a .DS_Store
file or any other hidden file created by the OS as on Mac. To follow along in this part, create an empty file in your repository called .DS_Store
and save it:
Switch back to Notepad.
Create a new file by typing Ctrl+N. This will open a new Untitled file that is empty.
Click File -> Save.
In the “Save as type” field click the drop-down menu and select “All files”.
In the File name field type
.DS_Store.
. Note the trailing period! That is, enter.DS_Store.
not.DS_Store
– if you don’t include the period at the end of the file name, Windows will automatically add.txt
to the end.Click “Save”
To tell Git to ignore a file:
Right-click the file you’d like it to ignore, in this case
.DS_Store
. On the drop-down menu, select “Ignore file (Add to .gitignore)”:Adding the file will make the selected file disappear in the Changes menu. In it’s place, you’ll see a
.gitignore
file has been created. The.gitignore
file is a simple text file that lists the names of any files in the repository that you want Git to ignore. Notice that GitHub Desktop has both created the file, and added.DS_Store
to it:As with any other file, we need to commit the changes to
.gitignore
for Git to keep track of it. Commit the change by clicking the “Commit 1 file to main” (note that the commit message automatically created by GitHub Desktop is “Create .gitignore”).From now on, any file named
.DS_Store
in this repository (meaning, in this folder and all sub-folders) file will not appear in your Changes menu, nor will you be able to commit changes to it to the repository.
III. Branches
You want to start working on titles for your stories, but you want to do it independently of your work on the story itself. To do that, let’s create a branch to specifically work on titles.
In GitHub Desktop, click on the “Current Branch” tab. This will show a drop-down menu showing all of the branches on your repository:
Currently, we only have one branch, which is called
main
. This is the Default branch, meaning it’s the branch you are placed in whenever you first create or clone a repository (more on cloning later). Think of it as the master copy of your repository. If this were a code repository, themain
would be the branch that you (try to) keep a clean, working version of your code.Let’s create a new branch on which we will develop our title. Click the “New Branch” button in the upper right. You will be prompted to create a name. Call it
title-dev
, then click “Create Branch”:You are now on a new branch called
title-dev
. You can see that by looking at the Current Branch at the top: it says title-dev:You can switch between branches by clicking the “Current Branch” drop-down menu, then selecting the branch you want:
Going back and forth between
main
andtitle-dev
, you’ll see that at the moment, thetitle-dev
branch is identical to themain
branch. You can verify that by viewing the contents of the repository in Explorer (Windows) / Finder (Mac). Click the “Show in Explorer” (Windows) / “Show in Finder” (Mac) button. You’ll see thatstory.txt
is still there no matter if you’re ontitle-dev
ormain
.Likewise, the commit history for
title-dev
is also the same asmain
: switch to thetitle-dev
branch then click on the History tab. You’ll see the same 4 commits as you have onmain
.Let’s do some development on
title-dev
. Switch to thetitle-dev
branch. Now let’s create a file calledtitle.txt
to store our title idea:- Windows users:
- Switch back to Notepad.
- Type Ctrl+N to create a new untitled file.
- Click File -> Save
- In the “File name” field enter
title.txt
then click “Save”.
- Mac users:
- Switch back to TextEdit.
- Type ⌘+N to create a new untitled file.
- Select Format -> “Make Plain Text”. (We need to do this to get the desired file extension.)
- Click File -> Save…
- In the “Save As” field type
title.txt
. - Click “Save”.
- Windows users:
Add a title to
title.txt
. Use your text editor to add:STAR FIGHT!
Save the change by typing Ctrl+S (Windows) / ⌘+S (Mac).
Go back to GitHub Desktop. You should see
title.txt
in the Changes sidebar, with the new lines shown in the diff:Commit the new changes by clicking “Commit 1 file to title-dev”. Note the default commit message is “Create title.txt”.
Satisfied with your title for now, go back to your main branch by clicking on the “Current branch” drop down and selecting
main
:Let’s see what happened to your files when you switched back to
main
. If you still have the Explorer/Finder window open, look at it. If not, click the “Show in Explorer” (Windows) / “Show in Finder” (Mac) button to view the contents of the repository.The
title.txt
file is gone!Likewise, if you click on the “History” tab in GitHub Desktop, you’ll see that your last commit is no longer in your history; you just have the first four commits.
This is because your last commit (and the file it created,
title.txt
) only exists on thetitle-dev
branch. To verify that it’s still there, click the “Current Branch” drop-down menu and switch to thetitle-dev
branch. You’ll see the “Create title.txt” commit reappear in your History. You’ll also see thetitle.txt
file reappear in your directory in Explorer/Finder. Toggling back and forth between the branches will make it disappear and reappear.What’s going on? In graph form, your repository currently looks like this:
Here, each dot represents a commit, and the different lines represent a different branch. Following a line illustrates the history as seen by that branch. Since the commits on
title-dev
live on their own branch, changes you make onmain
won’t affecttitle-dev
and vice versa (at least not until we merge the branches; more on that below).Let’s make some more changes to
story.txt
, but let’s do it on themain
branch. Switch tomain
using the “Current Branch” drop-down menu. Now use your text editor to add the following lines tostory.txt
:It is period of civil war. Rebel spaceships, striking from a hidden base, have won their first victory against the evil Galactic Empire.
Save the changes by typing Ctrl+S (Windows) / ⌘+S
Stage the commit by clicking the check mark next to
story.txt
in GitHub Desktop and change the commit message to “Add first pargraph”:Now commit the changes by clicking “Commit 1 file to main”.
Click on the History tab. Note that you now have 5 commits on master, none of which include the commits to
title-dev
branch.In a flash of brilliance, you get an idea for the title of your story. Quick! Switch to your
title-dev
branch by clicking the Current Branch -> title-dev.Now use your text editor to edit
title.txt
and changeSTAR FIGHT!
to:Star Wars A NEW HOPE by George Lucas
Nice work, George!
Save your changes to
title.txt
and stage the changes in GitHub Desktop by clicking the check box next totitle.txt
. Commit the changes by clicking the “Commit 1 file to title-dev”:Note that the commit message is “Update title.txt”.
Click on the History tab. Note that there are 6 commits here: the first four from
main
(before you branched off), and the last two ontitle-dev
:In graph form, your repo looks like this:
Merging
Satisfied that your title is perfect, you no longer feel the need to keep the title development on a separate branch. It’s ready to be merged on to the
main
branch. To do that, first switch to the main branch by clicking Current Branch -> main.Before merging
title-dev
on tomain
, we’re going to create a second copy ofmain
that we’ll callmain-bkup
. We’ll do that here so we can demonstrate squash and merge below. But when you first start using Git, it’s good practice to create a backup ofmain
before doing merges, as mistakes can happen that can be difficult to untangle. This way, you have the original state ofmain
preserved in the backup branch that you can always go back to.To create the copy of
main
:Click Current Branch. Make sure you’re on
main
(the checkmark is next tomain
), then click “New Branch”:This will open the “Create a Branch” window. Type
main-bkup
in the Name field, then click “Create Branch”. You will now be on themain-bkup
branch.Now go back to the
main
branch by clicking “Current Branch -> main”.
Now click the Current Branch drop-down menu again, and this time click the “Choose a branch to merge into main” button:
Select the
title-dev
branch. The button at the bottom will turn to blue and say “Create a merge commit”. Click that to merge the branch:Congratulations! You’ve made your first merge on to main. To see what happened, click on the History tab to see what the history on the main branch looks like now:
The commits you made on
title-dev
are now inmain
, along with a final “Merge” commit at the end. This final “merge” commit is to indicate that some of the commits in the history came from another branch (and what the name of the branch was).If you look at Explorer/Finder, you’ll see that
title.txt
is now in your directory when you’re onmain
. If you switch betweenmain
andtitle-dev
,title.txt
remains in both. Note that the history ontitle-dev
is unaffected by the merge: merging only changes the branch you merged into, not the branch you merged from.In graphical form, you
main
branch now looks like this:
Squash and merge: the cleaner history
When we were preparing to merge title-dev
, you may have noticed there was a drop-down button next to the “Create a merge commit” button:
If you had clicked that, you are presented with three options – merge, squash and merge, and rebase:
Let’s see would have happened if we selected squash and merge instead by doing a squash and merge on to main-bkup
.
Switch to the
main-bkup
branch by clicking “Current branch -> main-bkup”.Click “Current branch” again, and select “Choose a branch to merge into main-bkup”. Select “title-dev”, then click the drop down arrow next to the “Create a merge commit button”:
Select “Squash and merge”. This will change the blue button to read “Squash and merge”. Click that to do the squash and merge.
Click the History tab to see what the history on
main-bkup
looks like:The two commits that were done on
title-dev
, as well as the final merge commit, have all been “squashed” into a single large commit, which is placed at the end of the history onmain-bkup
. In graphical form, the history onmain-bkup
now looks like this:The contents of
main-bkup
are exactly the same asmain
, just the history is different. (You can verify this by switching betweenmain
andmain-bkup
.)
When do you use squash and merge vs merge?
It’s up to you, as each has its pros and cons:
Merge
- Pros:
- Preserves entire development history.
- If multiple authors contributed to a development branch, their contributions are attributed in the history. This makes it easier to tell who did what using
git blame
.
- Cons:
- Makes for a complicated history.
- Development branches can consist of many small commits. You probably don’t want every little “fix typo” commit in your history on
main
.
Squash and merge
- Pros:
- Makes for a much cleaner history: all new developments are contained in a single commit.
- GitHub Desktop will formulate the merge commit message to include all the commit messages from the development branch for reference.
- Cons:
- It will look as though one person wrote all the changes in the commit since all the commits on the development branch are condensed into a single commit. If multiple people contributed to the branch, their attribution is lost, making it difficult to know who did what using
git blame
. Their attribution can be worked out from looking at the commit message and referring to the development branch (if it’s not deleted), but this can be tedious.
- It will look as though one person wrote all the changes in the commit since all the commits on the development branch are condensed into a single commit. If multiple people contributed to the branch, their attribution is lost, making it difficult to know who did what using
Personally, I use Squash and Merge most of the time to keep the history on main
clean and straight forward (this is particularly nice on GitHub when using pull requests, as it will refer to the PR in the commit message; we will see this in exercise 3). But when working with someone else on a branch I will sometimes use Merge instead.
There is another way to merge branches called rebasing. Rebasing changes the history of the development branch to make it look like all the commits came after the last commit on main. This is mostly useful for keeping a development branch up to date with main
. For more on rebasing, see this article by the Atlassian corporation: Merging vs. rebasing.
Deleting branches
Now that you’ve merged your title-dev
branch, you can delete it to save space. To do that, click Current Branch, then right click title-dev
. This will yield a drop-down menu. Select “Delete branch”:
You will be prompted with a warning. Click the “Delete” button. The title-dev
branch will be gone! You can also delete main-bkup
now if you like.
Challenge Questions: Editing the same file on different branches
In the above example we only made changes to different files on our two branches: on main
we only edited story.txt
, while on title-dev
we only edited title.txt
. However, there is nothing stopping us from editing the same file concurrently on two different branches. The following questions will illustrate how that works.
IV. Resolving merge conflicts
As illustrated in the Challenge Questions, if the same lines in the same file are modified on two different branches, git
will not know how to merge the changes. This is called a merge conflict. In this case, git
will ask you to reconcile the differences. To illustrate, let’s try merging dev2
into main
after making the changes to list.txt
discussed in Question 3 above:
If you have not done so, try to merge
dev2
intomain
after making the changes to the second line oflist.txt
discussed in Question 3:- Switch to
main
: Click Current Branch -> main. - Click Current Branch -> Choose a branch to merge into “main”.
- Select dev2, then click “Create a merge commit” (note that a message pops up above the button that says there be 1 conflicted file).
- Switch to
When you try to do the merge, you will get the Resolve conflicts box:
This tells you what files are conflicted (in this case
list.txt
).To fix this, we need to manually resolve the conflict. There are several options to deal with this. If you have VS Code or some other code editor installed, you will see an option to open the file in that program. Here, though, we’ll use our simple text editor to resolve the issue.
Open list.txt with your text editor. You should see the following:
delta <<<<<<< HEAD easy ======= echo >>>>>>> dev2 foxtrot
git
has added the conflicting lines from both branches to the file, along with information about the two branches. The line as it appears onmain
is prefaced with<<<<<<< HEAD
. This indicates that the following line(s) is (are) how it appears on the branch being merged into. The line(s) is (are) followed by a=======
.After the
=======
the line(s) as it/they appear(s) on the branch being merged are shown. These are followed by>>>>>>> BRANCH_NAME
(here,BRANCH_NAME
isdev2
).We are free to edit the file anyway we like to resolve the conflict. You should remove the
<<<<
,====
, and>>>>
lines thatgit
has added, along with the edit you want to make to resolve the conflict.In this case, let’s keep the edit as it appears on
dev2
, and remove the edit onmain
. Delete the appropriate lines so that the file looks like:delta echo foxtrot
Then save and exit the file.
As soon as you save the changes to
list.txt
, the merge conflict window in GitHub Desktop will change to show that all conflicts have been resolved:Click “Continue Merge”.
The merge conflict is resolved! If you click on the History tab you will see the history with all the commits in it, as if you had a merged without any issue.
Merge conflicts happen, but can be fixed fairly easy. If there were multiple areas in a file that caused a conflict, the conflicting areas would all be surrounded by the same <<<<<<<
/=======
/>>>>>>>
lines that we saw above. You’ll want to search through the file for those to make sure you got all the conflicts. If multiple files had conflicts, git
will make you resolve all of them before allowing the merge to complete.
Summary
That’s the basics of how to use git
. In the following parts we’ll see how to use this with GitHub and how to collaborate with partners using git
and GitHub.