Practise the basics of Git on the command line: create a repository,
stage and commit changes, keep secrets out of it, and work with branches and
merges.
On this pageTable of contents
Legend
Parts of this exercise are annotated with the following icons:
A task you MUST perform to complete the exercise
Optional step that you may perform to make sure that
everything is working correctly, or to set up additional tools that are not required but can
help you
Advanced tips on how to go further (or
challenges!)
The end of the exercise
The architecture of the software you ran or
deployed during this exercise
Troubleshooting tips: how to fix common problems you might
encounter
Each exercise asks you to predict what Git will do before you check it.
Write your prediction down, then run the command and compare. A wrong prediction
is not a failure: it is exactly the misunderstanding the exercise is there to
reveal. Each exercise has a solution you can reveal to check your answers.
Set up Git
Git may already be set up on your computer. Check each of these, and only change
what is missing.
Is Git installed?
$>git--version
gitversion2.55.0
Any recent version is fine. If the command is not found, install Git:
On macOS, run xcode-select --install, which installs the command-line
tools, Git included.
On Windows in the WSL, or on Linux, install it with your package
manager, for example sudo apt install git.
If either command prints nothing, or you get a default identity (macOS typically
makes up an identity from your computerβs user name and host name, such as
jdoe@MacBook-Pro.local), then you should configure your own name and e-mail
address:
$>gitconfig--globaluser.name"John Doe"
$>gitconfig--globaluser.emailjohn.doe@example.com
Without this configuration, Git either refuses to commit, or records your
default identity in your commits.
The default branch
Check that new repositories start with a branch called main:
$>gitconfiginit.defaultBranch
main
If it prints nothing, set it:
$>gitconfig--globalinit.defaultBranchmain
Otherwise, git init calls the first branch master, and prints a long
warning about it every time.
Your editor
Some Git commands open an editor, for example to write a merge commit message.
Check that yours is nano, which you set up in Hello Shell:
git graph draws the graph in your terminal. For a more readable picture,
install the Git Graph extension in Visual Studio Code. Open a
repositoryβs directory in Visual Studio Code, then click Git Graph in the
status bar at the bottom of the window.
Warning
On Windows, your repositories are in the WSL, and Git Graph only sees them
if Visual Studio Code is opened in the WSL too. Open it from your WSL terminal,
in the repositoryβs directory:
$>code.
The first time, this installs what Visual Studio Code needs to work in the WSL.
Then install the Git Graph extension again in the WSL, where Visual Studio
Code offers to.
Create a repository
Create a directory for a new project, and move into it:
$>cd/path/to/projects
$>mkdirhello-git
$>cdhello-git
Predict: what will git status print here? Then check:
$>gitstatus
Check your prediction
The directory is not a repository, and neither is any of its parents:
This is how you check that you are not already in a repository before
running git init. If git status had printed a status instead, you would have
been inside an existing repository, and git init would have created a second
one nested inside it.
Look at what is staged with git diff --cached. It shows the one line of the
new file:
$>gitdiff--cached
diff--gita/hello.txtb/hello.txt
newfilemode100644
index0000000..557db03
---/dev/null
+++b/hello.txt
@@-0,0+1@@
+HelloWorld
You are about to commit with git commit -m "Add hello.txt".
Predict: which files will be in this commit?
Check your prediction
Only hello.txt. A commit contains only what is staged: hi.txt is not, so
it stays untracked, outside the commit.
Commit:
$>gitcommit-m"Add hello.txt"
[main(root-commit) a82bb9b]Addhello.txt
1filechanged,1insertion(+)
create mode 100644 hello.txt
Your commitβs hash will be different from a82bb9b: it is computed from the
commitβs content, which includes your name and the date.
Check with git status that hi.txt is still untracked, and look at the
history with git log.
Tip
When the output of git log or git diff is longer than your terminal, Git
shows it one screen at a time, and does not give you your prompt back. Scroll
with the arrow keys, and press q to quit.
Finally, commit the other file too:
$>gitaddhi.txt
$>gitcommit-m"Add hi.txt"
Staged and modified
Add a line to hello.txt, and stage it:
$>echo"You are beautiful">>hello.txt
$>gitaddhello.txt
Before committing, add another line to the same file:
$>echo"I see trees of green">>hello.txt
Predict: what will git status say about hello.txt? Then check:
$>gitstatus
Check your prediction
hello.txt appears twice in the status: once as staged, and once as
modified but not staged.
git add put a snapshot of the file as it was when you ran it into the
staging area: with βYou are beautifulβ, but without βI see trees of greenβ,
which you wrote afterwards. The working directory and the staging area now hold
two different versions of the same file.
Predict: which line will git diff show? Then check:
$>gitdiff
Check your prediction
git diff compares the working directory with the staging area. It shows what
you have changed but not staged: the second line.
$>gitdiff
diff--gita/hello.txtb/hello.txt
index2136a8e..730ea5a100644
---a/hello.txt
+++b/hello.txt
@@-1,2+1,3@@
HelloWorld
Youarebeautiful
+Iseetreesofgreen
Predict: which line will git diff --cached show? Then check:
$>gitdiff--cached
Check your prediction
git diff --cached compares the staging area with the last commit. It shows
what you have staged: the first line.
$>gitdiff--cached
diff--gita/hello.txtb/hello.txt
index557db03..2136a8e100644
---a/hello.txt
+++b/hello.txt
@@-1+1,2@@
HelloWorld
+Youarebeautiful
You are about to commit with git commit -m "Tell the world it is beautiful".
Predict: which lines will this commit add?
Check your prediction
Only βYou are beautifulβ. A commit saves the staging area, not the working
directory, so it saves the version of hello.txt that git diff --cached
showed you.
Commit:
$>gitcommit-m"Tell the world it is beautiful"
Predict: what will git status say now? Then check:
$>gitstatus
Check your prediction
The second line is still there, modified but not staged:
The -a option stages every modified file that Git already tracks before
committing.
Ignore a secret
Applications often read secrets, such as database passwords, from files that
must never be shared. Other types of files, such as logs, are also not meant to
be in the repositoryβs permanent history. Create a secret file, and a log file
too:
Both files are untracked, so git add . would now put your password in the
history. Tell Git to ignore both files, by creating a .gitignore file that
lists them:
$>echo".env">.gitignore
$>echo"*.log">>.gitignore
$>cat.gitignore# check the contents
Predict: what will git status say now? Then check:
$>gitstatus
Check your prediction
The ignored files disappear from the status. Only the new .gitignore file is
left, untracked:
git add . is now safe: it stages the .gitignore file, and skips .env and
debug.log. Commit the ignore file:
$>gitadd.
$>gitcommit-m"Ignore secrets and logs"
Question: why commit the .gitignore file, rather than keep it on your
machine?
Check your answer
The .gitignore file is committed so that it is part of the project:
everyone who works on it gets the same list, and nobody commits .env by
mistake on their own machine.
A secret committed too late
Your application now needs an API key. Create a file for it, and commit your
work as you usually do:
$>echo"API_KEY=sk-9f8e7d6c5b4a">api-key.txt
$>gitadd.
$>gitcommit-m"Configure the API"
Oops: api-key.txt was not in your .gitignore, so git add . staged it, and
it is now in a commit. Add it to the ignore file, and replace the key with a new
one:
$>echo"api-key.txt">>.gitignore
$>echo"API_KEY=sk-0a1b2c3d4e5f">api-key.txt
Predict: what will git status say about api-key.txt? Then check:
$>gitstatus
Check your prediction
Adding the file to .gitignore changes nothing: Git still tracks it, and sees
the new key as a modification:
.gitignore only applies to files Git does not track yet. Once a file has
been committed, ignoring it has no effect until you stop tracking it.
To make Git stop tracking the file, while keeping it on your disk, remove it
from the staging area only, then commit that along with the ignore file:
$>gitrm--cachedapi-key.txt
$>gitadd.gitignore
$>gitcommit-m"Stop tracking the API key"
Check that api-key.txt is still in your directory with ls, and that
git status no longer mentions it.
Predict: is the first key, sk-9f8e7d6c5b4a, gone from the repository? Then
check the history of the file:
$>gitlog-p--api-key.txt
Check your prediction
The first key is not gone. The commit βConfigure the APIβ still contains it,
and always will: every commit is a permanent snapshot.
$>gitlog-p--api-key.txt
...
ConfiguretheAPI
diff--gita/api-key.txtb/api-key.txt
newfilemode100644
index0000000..a4578ba
---/dev/null
+++b/api-key.txt
@@-0,0+1@@
+API_KEY=sk-9f8e7d6c5b4a
Anyone who gets a copy of this repository gets that key too. Once a secret has
been committed, and especially once the repository has been shared, consider it
leaked: the only real fix is to change the secret itself, here by revoking
the key and getting a new one. This is why the .gitignore file comes first,
before the secret.
It is possible to remove a file from the entire history of a repository,
with dedicated tools such as git filter-repo. But since a
commit is named by the hash of its content, and every commit points to its
parent, this changes the commit that added the file, and every commit after
it: they all get new hashes. The result is a different history.
That comes at a cost. Everyone else who works on the repository has to throw
away their copy of the old history and start again from the new one, or their
next merge brings the old commits, and the secret, right back. Any work they
based on the old commits has to be moved onto the new ones. Itβs a perfectly
good way to make your colleagues angry.
And it does not help with the leak itself: anyone who copied the repository
before the rewrite still has the secret. So even after rewriting the history,
the secret must be changed. GitHubβs guide to removing sensitive
data describes the whole procedure.
Branch and switch
Still in hello-git, create a branch:
$>gitbranchbye
Predict: which branch are you on now? Check with git branch, which lists
the branches, with a star next to the current one:
$>gitbranch
Check your prediction
Creating a branch does not switch to it: the star is still on main.
$>gitbranch
bye
*main
Then switch to the new branch, and commit a new file on it:
$>gitswitchbye
$>echo"Goodbye World">goodbye.txt
$>gitaddgoodbye.txt
$>gitcommit-m"Say goodbye"
Predict: here are the last few commits of the graph, with the main, bye
and HEAD pointers, before you switched to bye and committed. Predict what
the graph looks like now, after the switch and the commit. Then play the diagram
to check your prediction:
Check your prediction
bye has moved forward to the new commit, with HEAD, and main has stayed
where it was. Check yours with git graph, and/or with VSCodeβs Git Graph
extension:
$>gitgraph
* 4d2684e (HEAD->bye)Saygoodbye
* dc04e3e (main)StoptrackingtheAPIkey
*6c3bb3cConfiguretheAPI
...
Now switch back:
$>gitswitchmain
Predict: predict what the switch changes in the graph. Then play the diagram
to check your prediction:
Predict: does goodbye.txt still exist? Then check with ls.
Check your prediction
No: switching rewrote the working directory to match the snapshot main points
to, which does not have the file.
api-key.txt, debug.log and .env are still there: they are ignored, so Git
does not touch them when you switch.
Predict: will git log --oneline show the βSay goodbyeβ commit? Then check:
$>gitlog--oneline
Check your prediction
No: git log only shows the history of the commit HEAD points to, and βSay
goodbyeβ is not in the history of main. git graph shows it because of its
--all option, which shows the history of every branch.
Switch to bye again: goodbye.txt is there again, and βSay goodbyeβ is in the
history. The file was never lost, only stored in the commit. Then come back to
main.
Two merges
This exercise uses a prepared repository, with a history already made for you.
Get it, and move into it:
The repository has three branches on GitHub, but cloning only creates main on
your machine. Switch to each of the other two once, which creates them, then go
back to main and remove the link to GitHub, which you will learn about with
remotes:
$>gitswitchfix-typo
$>gitswitchcontact-page
$>gitswitchmain
$>gitremotermorigin
Look at the graph, with git graph and/or with VSCodeβs Git Graph extension:
You are on main. You want to bring both fix-typo and contact-page into it,
one after the other.
Merge fix-typo
You are going to merge fix-typo into main, with git merge fix-typo.
Predict: will the merge be a fast-forward, or will Git create a merge
commit?
Check your prediction
A fast-forward. fix-typo is directly ahead of main: its commit comes
right after the one main points to. Git only has to move main forward, and
creates no commit.
Merge:
$>gitmergefix-typo
Updatingb85d48f..27d2a53
Fast-forward
about.html|2+-
1filechanged,1insertion(+), 1 deletion(-)
Predict: predict what the merge changes in the graph. Then play the diagram
to check your prediction:
Merge contact-page
You are now going to merge contact-page into main, with
git merge contact-page.
Predict: will the merge be a fast-forward, or will Git create a merge
commit?
Check your prediction
A merge commit. contact-page has diverged from main: it was created from
βAdd an about pageβ, and main has two more commits since. Git performs a
three-way merge from the common ancestor, 3947df4, and creates a merge
commit with two parents.
Merge. This time, Git opens your editor with a commit message that it has
written for you. Keep it as it is, and exit: in nano, press Ctrl-X. If you
find yourself in Vim instead, see I am stuck in Vim.
$>gitmergecontact-page
Mergemadebythe'ort'strategy.
contact.html|11+++++++++++
index.html|1+
2fileschanged,12insertions(+)
createmode100644contact.html
Predict: predict what the merge changes in the graph. Then play the diagram
to check your prediction:
Check your prediction
Check yours with git graph:
$>gitgraph
* b91b87f (HEAD->main)Mergebranch'contact-page'
|\
| * 54bd3ee(contact-page) Link tothecontactpage
|*591343fAddacontactpage
*|27d2a53(fix-typo)Fixatypoontheaboutpage
*|b85d48fImprovethestyle
|/
*3947df4Addanaboutpage
*72208e4Createthehomepage
Your merge commitβs hash will be different from b91b87f, but the other hashes
will be the same as these, since you cloned these commits.
Merge in the reverse order
This question is harder, and optional.
Predict: what if you had merged contact-page first, then fix-typo? Would
fix-typo still be merged as a fast-forward?
Check your prediction
No: this time, fix-typo needs a merge commit too.
Merging contact-page first is a three-way merge, as before, and creates a merge
commit on main. But fix-typo does not have that merge commit in its history:
main has moved on since fix-typo was created, so the two have diverged, and
merging fix-typo is a second three-way merge, with a second merge commit.
Whether a merge can be a fast-forward does not depend on the branch you merge:
it depends on the shape of the history at the moment you merge it.
Check it, in a second copy of the repository, cloned into another directory:
Both merges open your editor: keep each message as it is, and exit.
Predict: predict the graph you end up with. Then play the diagram to check
your prediction:
Check your prediction
Check yours with git graph:
$>gitgraph
* a2e7d63 (HEAD->main)Mergebranch'fix-typo'
|\
| * 27d2a53(fix-typo)Fixatypoontheaboutpage
*|b175f11Mergebranch'contact-page'
|\ \
||/
|/|
| * 54bd3ee(contact-page) Link tothecontactpage
|*591343fAddacontactpage
*|b85d48fImprovethestyle
|/
*3947df4Addanaboutpage
*72208e4Createthehomepage
The two branches, and the changes they bring, are the same as before, and so are
the files you end up with. But the history is different: two merge commits
instead of one.
History hunt
This exercise is optional. Every project on GitHub comes with its whole
history, and you can search it without leaving your terminal. Clone the
repository of 2048, the puzzle game that went viral in 2014, next to
your hello-git directory (not inside it):
Then answer the questions below. Each one names the command that finds the
answer. Remember that you leave git log by pressing q.
The first commit
When was the first commit of the game made, and by whom? What was its message?
git log shows the most recent commits first. git log --reverse shows the
oldest first.
Answer
$>gitlog--reverse
commitf4d95b6...
Author:GabrieleCirulli<...>
Date:WedMar515:20:562014+0100
initialcommit
Gabriele Cirulli made it on 5 March 2014. The rest of that dayβs commits style
the page and write the README: the code that moves the tiles only arrives three
days later.
Ads for a day
In 2018, the author added ads to the game. How long did they stay?
git log --grep <text> only shows the commits whose message contains the text,
and -i makes the search ignore uppercase and lowercase.
Answer
$>gitlog-i--grepads
commitfc1ef4f...
Author:GabrieleCirulli<...>
Date:SatOct2718:25:122018+0200
RemoveAdsensecode
commitffa8559...
Author:GabrieleCirulli<...>
Date:SatOct2713:21:452018+0200
AddAdSensecode
About five hours, on 27 October 2018. The messages say βAdSenseβ and βAdsenseβ,
Googleβs advertising service, which both contain βAdsβ with a capital A: without
-i, git log --grep ads finds nothing.
How do you win?
Find the commit that added the win condition, and look at the code it added.
What exactly makes you win?
Search the messages with --grep, then show the commit with
git show <hash>, which prints its message and its changes.
Answer
$>gitlog--oneline--grepwin
...
e65111faddwincondition
$>gitshowe65111f
...
+//Themighty2048tile
+ if (merged.value===2048)self.won=true;
You win as soon as two tiles merge into a 2048 tile.
The best score
The game remembers your best score in the browserβs storage, localStorage.
Who wrote the commit that first used it?
A commit message does not always name what the code does. git log -S <text>
searches the changes instead: it shows the commits that added or removed the
text.
Answer
$>gitlog--oneline--reverse-SlocalStorage
664546eStorebestscoreinlocalStorage
...
$>gitshow664546e
commit664546e...
Author:TimPetricola<...>
Tim Petricola, on 10 March 2014, five days after the first commit. This one
could also be found with --grep "best score", but -S finds code whatever the
message says.
Who helped?
How many people have made commits in this project, and who made the most after
its author?
git shortlog -sn counts the commits of each author.
Answer
$>gitshortlog-sn
131GabrieleCirulli
6LaurentMargirier
6sigod
5TimPetricola
...
28 names, and Laurent Margirier and sigod tie after the author. But a name is
only what each author configured with git config user.name: the README says
that Anna Harrenβs GitHub account is iirelu, and both names are in the list.
Three commits with the same message
The user rayhaanj made three commits with the same message. Find them with
git log --author, and look at each one with git show. What are they, and why
are there three?
Answer
$>gitlog--oneline--authorrayhaanj
96e9290Addedvimkeybindings
fb8eabeAddedvimkeybindings
29c4beaAddedvimkeybindings
29c4bea and fb8eabe add the same keyboard shortcuts, H, J, K and L, which
move around in Vim. Both start from the same parent, and they only differ by a
space. 96e9290 is a merge commit: git show prints a Merge: line with its
two parents, the two other commits. Their author made the change twice on
diverging histories, and merged them. You can see it by drawing the graph from
the merge commit rather than from the latest one: git graph -4 96e9290 (or
git log --graph --oneline -4 96e9290 if you did not create the alias).
The shortcuts are still in the game today: try them. And the message, three
times the same, cannot tell the three commits apart.
A renamed file
The gameβs stylesheet is style/main.scss. Has it always had that name?
git log -- <file> shows only the commits that changed a file, and --follow
keeps following it when it was renamed. Compare the two, and add
--name-status to see what each commit did to the file.
It was created as style.scss at the root of the project in the second commit,
then moved into style, then renamed to main.scss. Without --follow, the
history stops at the last rename. A, M and R mean added, modified and
renamed.
What have I done?
You kept the history of a project: every version you committed is still there,
to go back to, compare, or build on in parallel. All of it lives in the hidden
.git directory at the root of your project, the Git directory. Without it,
your files stay but their history is gone. Copied elsewhere, it carries the
whole history with it, which is what git clone does.
Along the way, you:
Created a repository and made commits.
Committed a file that was both staged and modified.
Ignored files, and stopped tracking one that was committed too late.
Created branches, switched between them, and merged them.
(Optionally) searched the history of a real project.
A commit saves the staging area, not your files. Git keeps your project in
three places: the working directory, where you edit; the staging area, where you
prepare the next commit; and the Git directory, where commits are stored. git add copies a file from the first to the second as it is at that moment, which
is how hello.txt could be both staged and modified. git status tells you
where each change is.
A commit is a snapshot of the whole project, named by the hash of its
content. Change anything in it, even its author or its date, and it becomes a
different commit, which is why the commits you made do not have the hashes shown
on this page. A commit, once made, never changes.
That is why your first API key is still in the history, even after you stopped
tracking it, and anyone with a copy has it. The only real fix for a committed
secret is to change it. .gitignore only protects files Git does not track yet,
so it has to come before the secret, and it is committed so that everyone on
the project shares it. Keeping secrets out of the code comes back later in the
course.
A branch is only a pointer to a commit, and HEAD says which one you are
on. Committing moves the current branch forward. Switching moves HEAD and
rewrites your working directory to match another snapshot. Nothing is lost when
you switch: goodbye.txt disappeared from main, but it was still in the
commit of bye.
How Git merges depends only on the shape of the history. When the other
branch is directly ahead, as fix-typo was, Git just moves the pointer forward:
a fast-forward. When the two have diverged, as contact-page had, Git combines
what each side changed since their common ancestor into a merge commit, which
has two parents. Merged in another order, the same branches give the same files
but a different history.
If you went on the history hunt, you also saw that a history is something you
can search, and that an authorβs name is only what they configured.
So far, your history has lived in a single copy, on your computer. In
Collaborating with Git, you share it with others through a
remote, where diverged histories come back as refused pushes and conflicts.
Later in the course, a repository is also how you put your application on your
server.
Going further
The exercises below are optional. They practise other Git commands that are
useful in everyday work, but that you will not be asked about in the exam. Do
them in your hello-git repository, on main, and use git status after each
step to see what happened.
Unstage a file
Modify a file and stage it:
$>echo"Hi Jane">>hi.txt
$>gitaddhi.txt
Check with git status that the change is staged. Then take it back out of the
staging area:
$>gitrestore--stagedhi.txt
Check again with git status and cat hi.txt: the change is no longer staged,
but it is still in the file.
Discard a change
Throw the change away:
$>gitrestorehi.txt
Check with git status and cat hi.txt. The change is gone for good: it was
never committed, so Git has no copy of it.
Fix the last commitβs message
Make a commit with a typo in its message:
$>echo"Hi Steve">>hi.txt
$>gitcommit-am"Greet Stve"# add and commit in one step
# with -am (same as -a and -m)
Look at it with git log --oneline, and note its hash. Then fix the message:
$>gitcommit--amend-m"Greet Steve"
Predict: will the commit still have the same hash? Why? Then check with
git log --oneline.
Check your prediction
No. Amending does not modify the commit, it replaces it with a new one. A
commit is named by the hash of its content, and its message is part of that
content, so a new message makes a different commit. The old commit is no longer
on any branch.
This is why you should not amend a commit you have already shared: the others
still have the old commit, and their history no longer matches yours.
Add a forgotten file to the last commit
Create two files, but only stage one of them before committing:
$>echo"a">a.txt
$>echo"b">b.txt
$>gitadda.txt
$>gitcommit-m"Add a and b"
Check with git log --stat -1, which shows the files changed by the last
commit: b.txt is not in it. Note the commitβs hash, then add the file to the
same commit:
$>gitaddb.txt
$>gitcommit--amend
Your editor opens with the commitβs message. Keep it as it is, and exit: in
nano, press Ctrl-X. Check again with git log --stat -1 that the commit now
contains both files.
Predict: is it still the same commit? Compare its hash with the one you
noted. Why has it changed, although the message is the same?
Check your prediction
No. The files a commit contains are part of its content too, and they now
include b.txt: amending replaced the commit with a new one, as it did for the
message.
The limits of commit -a
Modify hi.txt and create a new file, new.txt, then commit with -a only:
$>echo"Hi Alice">>hi.txt
$>echo"new">new.txt
$>gitcommit-am"Greet Alice"
Which of the two changes did the commit include? Why?
Check your answer
Only the change to hi.txt. The -a option stages the modified files that Git
already tracks. new.txt is untracked, so it is not in the commit, and
git status still lists it as untracked. A new file always needs a git add.
Rename a file
Rename a file with the mv command (or in your editor), and look at git status. Then stage everything with git add ., and look again. What changed in
how Git describes it?
Check your answer
Before git add, Git sees two separate changes: a tracked file that has been
deleted, and a new file that is untracked. For example, after
mv hello.txt hola.txt:
$>gitstatus
...
deleted:hello.txt
...
Untrackedfiles:
hola.txt
Once both are staged, Git notices that the new file has the same content as the
deleted one, and describes them as one rename:
$>gitadd.
$>gitstatus
...
renamed:hello.txt->hola.txt
Git does not record renames: a commit is a snapshot, which only says which files
exist and what they contain. Git works the rename out when it compares two
snapshots, from the content of the files.
The global ignore file
Some files are created by your operating system or your editor in every
directory, such as .DS_Store on macOS. Rather than ignoring them in every
project, ignore them once for your whole computer:
$>echo".DS_Store">>~/.gitignore# the .gitignore file in your home
$>gitconfig--globalcore.excludesFile~/.gitignore
Travel back in time
Switch to an old commit, using a hash from git log --oneline:
$>gitswitch--detacha82bb9b
Look at your files, and at git status, which says HEAD detached: HEAD
points directly to a commit instead of a branch. Come back with
git switch main.
Delete an unmerged branch
Your bye branch was never merged. Try to delete it with -d, then with -D.
Where did the βSay goodbyeβ commit go?
Check your answer
-d refuses, because βSay goodbyeβ is not in the history of any other branch:
deleting bye would leave no branch leading to it. -D deletes it anyway:
$>gitbranch-dbye
error:thebranch'bye'isnotfullymerged
...
$>gitbranch-Dbye
Deletedbranchbye(was4d2684e).
The commit is still in the repository. Only the pointer is gone: a branch is a
pointer to a commit, and deleting it does not delete the commit. But no branch
leads to it any more, so git log and git graph no longer show it, and Git
will eventually clean it up.
Look for it with git reflog, which lists every commit HEAD has pointed to
recently, and create a branch pointing to it again with git branch welcome-back <hash>.
Troubleshooting
Here are a few problems you may run into during these exercises.
fatal: not a git repository
You are not in a repository. Check where you are with pwd, and move into your
repositoryβs directory with cd. This is expected in create a
repository, before git init.
Author identity unknown
Git does not know your name and e-mail address, so it cannot record the author
of your commit, and refuses to make it:
Set the default as described in the default branch, for
your next repositories. Then rename the branch of the repository you just
created:
$>gitbranch-mmain
I am stuck in Vim
Git opened Vim to let you write or confirm a message. Press Esc, then type
:q! and press Enter. For a merge, Git then uses its own message; for a
commit, the message is empty and Git cancels the commit. To have Git open nano
instead, see your editor.
git log or git diff does not give my prompt back
The output was longer than your terminal, so Git shows it one screen at a time.
Scroll with the arrow keys, and press q to quit.
merge: fix-typo - not something we can merge
The branch does not exist on your machine: you removed the link to GitHub before
switching to it. Delete the hello-git-merges directory, clone it again, and
follow the steps in two merges in order.