Introduction
A collection of exercises for the OESA Git Workshop.
The workshop is intended to enable participants to work collaboratively using Git and GitLab on software and other projects.
No prior knowledge of Git is required. However, there are some prerequisites on software that needs to be installed to complete the exercises (see section Requirements).
We will use the Git command line interface (CLI) because it exposes the terms and concepts directly. We know this may seem inconvenient, and a number of GUI frontends and IDE integrations exist. However, if you know how to use the CLI, you should be able to understand and use any GUI.
How to use this book
In its current state, this book is not intended for self-study, as the context necessary to understand everything is provided in the workshop and is not laid out here. This may, however, change in a future version to make this book a stand-alone learning resource.
Each exercise proceeds on the state generated in the previous exercises. Thus, the intended way to use them is to work through them one by one. However, mind the limitations stated above.
The slides for the theory parts of the workshop are available as PDF here.
Requirements
UFZ GitLab account
To work with UFZ GitLab, an account is required there. On the UFZ GitLab login page (https://git.ufz.de/), use the Contact us
link and write a short email to the WKDV. You should get an account quickly, usually at the same day.
Alternatively, a free GitLab account at https://gitlab.com/ can be used.
Software
Essential software required to complete the exercises, and to work with Git in general, are:
- Git. Download the "official" Git client from Git - Downloads. Install with all settings as suggested by the installer!
- A text editor. Notepad (the Windows default) will do, but Notepad++ might be more comfortable to use
Further, we will use Pandoc in the exercises to convert Markdown files to HTML. It is not strictly required, but you may find it useful for your work also on other occasions.
On Windows, install Pandoc using the package installer available at https://pandoc.org/installing.html. For other platforms, see the instructions there.
Book sources
This book is generated from Markdown. Sources are available at UFZ GitLab:
https://git.ufz.de/oesa/git-exercises
Cloning
To view the sources locally, clone them:
git clone https://git.ufz.de/oesa/git-exercises.git
Contributing
If you have any suggestions how to improve this book, please create an issue or make a merge request with your suggested changes.
Start with Exercise 1
Exercise 1 - Linear workflow
In this exercise, you will learn the most basic Git commands for a simple linear workflow. You will make commits and inspect the project's history.
- Test the Git installation
- Git help
- Git settings
- Project setup
- Initialize a Git repository
- Make a first commit
- Make changes
- Inspect the history
- Amend a commit
- Check out older states
Test the Git installation
Open the console ("Eingabeaufforderung").
To test your git installation, run the following, which should print the installed Git version
git --version
Output
git version 2.30.0.windows.2
Git help
Help overview
git --help
Help on a specific command
git <command> -h
git <command> --help
Git settings
User name and email
Git needs a user name and email address to attribute your changes. We set them with
git config --global user.name "<Your Yame>"
git config --global user.email "<your.name>@ufz.de"
Line endings
Line endings are differnt in Unix compared to Windows. therefore, we need to set how they are handled
git config --global core.autocrlf true
Default text editor
Further, we set the default text editor to notepad
, the Windows default editor
git config --global core.editor notepad
Default branch
To avoid the outdated, oppressive default branch name master
, which is perceived as being related to slavery, we change it to main
git config --global init.defaultBranch main
All these setting are now global, you don't need to repeat them for every new project.
Project setup
Create a directory for your project (C:\Projects\git-workshop
)
C:\Users\username>cd C:\
C:\>mkdir Projects
C:\>cd Projects
C:\Projects>mkdir git-workshop
C:\Projects>cd git-workshop
C:\Projects\git-workshop>
From here on, we assume C:\Projects\git-workshop
as the working directory of the prompt.
Initialize a Git repository
Initialization of a repository is done with a single, simple command
git init
Output
Initialized empty Git repository in C:/Projects/git-workshop/.git/
We can inspect our project's directory content (with the option to show hidden files)
dir /A:H
Output
...
27/01/2021 13:17 <DIR> .git
0 File(s) 0 bytes
1 Dir(s) 517,128,151,040 bytes free
Git created a directory .git
, which is where the repository history is stored. You don't need to do anything with this directory, just for your information...
Make a first commit
Create a file README.md
1
echo.> README.md
You can also create the file using the Explorer, but depending on your settings you may end up with
README.md.txt
, which may be complicated to change.
Open the file with your text editor and fill it with
# Git Workshop
Content
* ...
* ...
* ...
Save your changes.
View the status of your project
git status
Output
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)
We need to "stage" our changes to be able to commit
git add README.md
View the status again to see what happened
git status
Output
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
And finally, commit (with a message)
git commit -m "initial commit"
Output
[main (root-commit) d8d9072] initial commit
1 file changed, 7 insertions(+)
create mode 100644 README.md
Please note that hashes (the 7-digits hex code in the first line) will be different in your output.
Check the status again to see that there is "nothing to commit, working tree clean".
git status
Output
On branch main
nothing to commit, working tree clean
Make changes
Let's take some notes of what we did. Create a file linear-workflow.md
echo.> linear-workflow.md
Fill it with some content, e.g.
# Linear workflow
```
git init
```
* Create file README.md
```
git status
git add README.md
git status
git commit -m "initial commit"
git status
```
Save your changes.
Inspect what changed (you should always do that before staging and committing!)
git status
Output
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
linear-workflow.md
nothing added to commit but untracked files present (use "git add" to track)
Stage the new file
git add linear-workflow.md
git status
Output
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: linear-workflow.md
To "un-stage" files use reset
git reset linear-workflow.md
git status
Output
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
linear-workflow.md
nothing added to commit but untracked files present (use "git add" to track)
Stage the file again
git add linear-workflow.md
git status
Output
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: linear-workflow.md
Commit
git commit -m "added linear workflow"
Output
[main 43bc0a8] added linear workflow
1 file changed, 15 insertions(+)
create mode 100644 linear-workflow.md
Inspect the history
To view the history of your project, use
git log
Output
commit 43bc0a86a7d49ad269f798360dfcea944713ef90 (HEAD -> main)
Author: ... <...@ufz.de>
Date: Wed Jan 27 20:27:02 2021 +0100
added linear workflow
commit d8d9072990da891df3624358b7a8fc473afb57f8
Author: ... <...@ufz.de>
Date: Wed Jan 27 20:25:35 2021 +0100
initial commit
We can also inspect the last commit with its message and diffs
git show
Output
commit 43bc0a86a7d49ad269f798360dfcea944713ef90 (HEAD -> main)
Author: ... <...@ufz.de>
Date: Wed Jan 27 20:27:02 2021 +0100
added linear workflow
diff --git a/linear-workflow.md b/linear-workflow.md
new file mode 100644
index 0000000..d039c21
--- /dev/null
+++ b/linear-workflow.md
@@ -0,0 +1,15 @@
+# Linear workflow
+
+```
+> git init
+```
+
+* Create file README.md
+
+```
+> git status
+> git add README.md
+> git status
+> git commit -m "initial commit"
+> git status
+```
\ No newline at end of file
Depending on the size of your console window, the last line displayed may be
...
. In this case, scroll down with the arrow keys until the last line shows(END)
. Then, pressQ
to finish.
Please not the last line,
\ No newline at end of file
. It is a Unix convention that any text file should end with a newline character (\n
), and as a programmer you should also follow this convention on other systems.
If you use the smallCopy to clipboard
icon in the top right corner of each code block instead of marking the text, it will automatically be copied with an extra newline at the end.
We can inspect an arbitraty commit by using its hash (at least the first 4 characters, typically 7). We view the first commit. Get the hash from the previous log
output
git show d8d9072
We can also compare arbitrary commits
git diff <old-hash> <new-hash>
git diff d8d9072 43bc0a8
The output should look similar to that of the two calls above, just showing other diffs.
Amend a commit
Oops, we forgot to link the file in README.md
. This is only a small change that belongs to our last commit. We don't want to make a new commit, but we can amend the previous one.
Add the link to README.md
and add an empty line at its end.
# Git Workshop
Content
* [Linear workflow](linear-workflow.md)
* ...
* ...
Also, fix the newline at the end of file linear-workflow.md
New file content
# Linear workflow
```
git init
```
* Create file README.md
```
git status
git add README.md
git status
git commit -m "initial commit"
git status
```
Check the status.
git status
Output
On branch main
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
modified: linear-workflow.md
With git diff
, we can also view changes in files compared to what is committed (actually, committed + staged).
git diff
Output
diff --git a/README.md b/README.md
index e266d1c..6ecdc70 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,6 @@
Content
+* [Linear workflow](linear-workflow.md)
* ...
* ...
-* ...
\ No newline at end of file
diff --git a/linear-workflow.md b/linear-workflow.md
index d039c21..fda7fd8 100644
--- a/linear-workflow.md
+++ b/linear-workflow.md
@@ -12,4 +12,4 @@
> git status
> git commit -m "initial commit"
> git status
-```
\ No newline at end of file
+```
git add README.md linear-workflow.md
git status
Output
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
modified: linear-workflow.md
To amend the last commit rather than create a new one, commit with option --amend
git commit --amend
As we did not enter a message this time, the text editor will pop up. Change the message if you want, save and close the editor.
Output
...
[main 1860049] added linear workflow
Date: Wed Jan 27 20:27:02 2021 +0100
2 files changed, 16 insertions(+), 1 deletion(-)
create mode 100644 linear-workflow.md
Inspect the history again to see that there is no new commit
git log
Output
commit 1860049c5afd2ffed4661e8e36745aec3da57183 (HEAD -> main)
Author: ... <...@ufz.de>
Date: Wed Jan 27 20:27:02 2021 +0100
added linear workflow
commit d8d9072990da891df3624358b7a8fc473afb57f8
Author: ... <...@ufz.de>
Date: Wed Jan 27 20:25:35 2021 +0100
initial commit
However, the hash of the top-most commit changed. Further, the diff of the last commit now contains our change
git show
We can also show the diff for a single file
git show README.md
Check out older states
Sometimes it may be necessary to revert a file to a state from the history, or just to view its old content.
git checkout 3cda487 -- README.md
(Use the hash of your first commit, it will be different!)
View the status to see what happened
git status
Output
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
We have staged changes in file README.md
. It is a bit of a quirk that the file is staged, but that's how it is. View the file in the text editor to note that is now looks like after your first commit.
To return to the latest version, check out the file for HEAD
git checkout HEAD -- README.md
git status
Output
On branch main
nothing to commit, working tree clean
echo.
writes text to the console. Using >
, we redirect this (empty) text to the file and thereby create it. The dot .
is required because without an argument (i.e. without text to write), echo
switches the echo mode on or off, instead of writing text.
Continue with Exercise 2
Exercise 2 - Non-linear workflow with branches
In this exercise, you will learn how to work with branches. You will create branches, merge them and resolve a conflict.
- Create a branch
- Make changes on a branch
- Switching between branches
- Another branch
- Merge
- Reset a branch
- Merge with an extra commit
- Merge with conflict
- Resolve conflicts
Create a branch
We want to take some further notes from the workshop. However, we will now work on different branches and start with the chapter on how to inspect the history. First, create a new branch inspect-history
git branch inspect-history
Let's list the branches we have now
git branch
Output
inspect-history
* main
Fine, but we are still on main
. Switch to inspect-history
and list branches again
git switch inspect-history
git branch
Output
* inspect-history
main
The
switch
command is relatively new in Git. On older versions, you have to usecheckout
instead. The commandcheckout
can do different things, depending on the context and the arguments. To reduce ambiguities, in newer versions of Gitswitch
can be used instead ofcheckout
to switch between branches, andrestore --staged
to un-stage changes.
We now have two branches and are currently on inspect-history
. When using git log
, you will see that both branches point to the same commit.
git log
Output
commit 1860049c5afd2ffed4661e8e36745aec3da57183 (HEAD -> inspect-history, main)
Author: ... <...@ufz.de>
Date: Wed Jan 27 20:27:02 2021 +0100
added linear workflow
commit d8d9072990da891df3624358b7a8fc473afb57f8
Author: ... <...@ufz.de>
Date: Wed Jan 27 20:25:35 2021 +0100
initial commit
BTW, HEAD
shows where you currently are.
There is also a shortcut that creates a branch and switches to it immediately
git switch -c inspect-history
Make changes on a branch
Create a new file inspecting.md
echo.> inspecting.md
Fill it with some content, e.g.
# Inspecting
## Inspect the history
```
git log
```
## Inspecting commits
```
git show
git show 3cda487
git show README.md
```
Save your changes.
Link it in README.md
and save again.
# Git Workshop
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* ...
Now, commit as usual
git status
git diff
git add README.md inspecting.md
git status
git commit -m "added page on inspecting the history"
Let's view the history again
git log
For a more compact view, use
git log --oneline
Output
eba0f8f (HEAD -> inspect-history) added page on inspecting the history
1860049 (main) added linear workflow
d8d9072 initial commit
You will see that branch inspect-history
is now one commit ahead of main
. I.e. it moved along with our changes, while main
did not.
Switching between branches
With Git, it is possible to work on multiple branches in parallel.
Using switch
, we can simply switch between branches.
Observe the content of your project folder. There are now three Markdown files.
Switch to main
and see the folder content again
git switch main
Now, the file inspecting.md
isn't there anymore.
When we switched to main
, Git replaced the files in our working copy with the version referenced by main
.
Switch to branch inspect-history
again to see that the working copy changes again and inspecting.md
is back again.
git switch inspect-history
Another branch
We now make some parallel edits on an additional branch.
First, switch to main
again, as we want to start from there rather than from inspect-history
git switch main
Create another branch amending-commits
where we will take notes on that aspect
git switch -c amending-commits
Create a new file amending.md
echo.> amending.md
Fill it the following content (and save...)
# Amending commits
```
git status
git diff
git add README.md
git commit --amend
```
Link the file in README.md
# Git Workshop
Content
* [Linear workflow](linear-workflow.md)
* [Amending commits](amending.md)
* ...
You may notice that the link to inspecting.md
has gone. This is because we went back to branch main
, which does not contain that change.
Commit as usual
git status
git diff
git add README.md amending.md
git status
git commit -m "added page on amending commits"
Let's inspect again what we have, with option --oneline
for a more compact view
git log --oneline
Output
0639ed4 (HEAD -> amending-commits) added page on amending commits
1860049 (main) added linear workflow
d8d9072 initial commit
You may be surprised where branch inspect-history
has gone. This is because by default, Git only shows what is part of the history of the current state, which inspect-history
is not. To see the entire history as a (directed acyclic) graph, add options --all
and --graph
git log --graph --oneline --all
Output
* 0639ed4 (HEAD -> amending-commits) added page on amending commits
| * eba0f8f (inspect-history) added page on inspecting the history
|/
* 1860049 (main) added linear workflow
* d8d9072 initial commit
You should see the entire graph now, and that we have diverged from main
in two different directions.
Merge
When the work on a branch is completed, it can be merged back into main
. To merge, you need to be on the branch you want to merge the other branch into. So we switch to main
git switch main
Now, merge amending-commits
into the current branch main
git merge amending-commits
Output
Updating 1860049..0639ed4
Fast-forward
README.md | 2 +-
amending.md | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
create mode 100644 amending.md
Inspect the graph again
git log --graph --oneline --all
Output
* 0639ed4 (HEAD -> main, amending-commits) added page on amending commits
| * eba0f8f (inspect-history) added page on inspecting the history
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Now, main
and amending-commits
point to the same commit, but somehow our branching topology has gone. This is because Git makes a so-called "fast-forward" merge in case there are no conflicts. We can prevent that with the option --no-ff
. But first, we have to undo the merge.
Reset a branch
To bring main
back to the state before the merge, we make a hard reset to the previous commit (use the correct hash, the 3rd counted from the top!)
git reset --hard 1860049
Output
HEAD is now at 1860049 added linear workflow
Inspect again to see that we have what we had before the merge
git log --graph --oneline --all
Output
* 0639ed4 (HEAD -> amending-commits) added page on amending commits
| * eba0f8f (inspect-history) added page on inspecting the history
|/
* 1860049 (main) added linear workflow
* d8d9072 initial commit
Merge with an extra commit
Now, we can merge without "fast-forward"
git merge amending-commits --no-ff
Output
Merge made by the 'recursive' strategy.
README.md | 2 +-
amending.md | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
create mode 100644 amending.md
Inspect again to see that the branching topology is preserved now
git log --graph --oneline --all
Output
* e25d3cc (HEAD -> main) Merge branch 'amending-commits'
|\
| * 0639ed4 (amending-commits) added page on amending commits
|/
| * eba0f8f (inspect-history) added page on inspecting the history
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Further, a new commit was created, with an automatic message (Merge branch 'amending-commits'
)
Merge with conflict
We can now try to also merge branch inspect-history
git merge inspect-history --no-ff
Output
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
Git says that automatic merging failed due to a conflict in README.md
, and that we should resolve the conflict and then commit. This is also a reminder to always read Git's output carefully.
To get some more insights, check the status
git status
Output
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: inspecting.md
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
Again, read carefully! We have unmerged paths.
Further, is says we can resolve the conflicts and commit, or abort.
merge
is an example of a modal command, i.e. we have to commit or abort the merge before we can continue to use Git normally.
For practice, we abort the merge and view the status:
git merge --abort
git status
Output
On branch main
nothing to commit, working tree clean
That was for practice. Now let's merge again and resolve the conflict.
git merge inspect-history --no-ff
Output
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
We get the same message as before: that automatic merging failed due to a conflict in README.md
.
Resolve conflicts
Open file README.md
. It has the following content
# Git Workshop
Content
* [Linear workflow](linear-workflow.md)
<<<<<<< HEAD
* [Amending commits](amending.md)
=======
* [Inspecting](inspecting.md)
>>>>>>> inspect-history
* ...
The content between <<<<<<< HEAD
and >>>>>>> inspect-history
is where the conflict is, with the first part on main
(our current HEAD
), and the second part on inspect-history
. Resolve the conflict and make the file look like this
# Git Workshop
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* [Amending commits](amending.md)
Now that the conflict is resolved we can stage as usual
git status
git diff
git add README.md
git status
Output
On branch main
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: README.md
new file: inspecting.md
Git tells us that all conflicts are fixed, but we are still merging. We do what it suggests and commit
git commit
Leave the message in the popup as is and close it.
Through the commit, we finished the merge and are now no longer in "merge mode". Confirm through checking the status
git status
Output
On branch main
nothing to commit, working tree clean
Inspect the graph again
git log --graph --oneline --all
Output
* fc527c5 (HEAD -> main) Merge branch 'inspect-history'
|\
| * eba0f8f (inspect-history) added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 (amending-commits) added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
We see two nicely merged branches.
To finish our work, we should delete the merged branches. They are only pointers and not needed anymore. The topology will remain untouched by deleting them
git branch --delete amending-commits
git branch --delete inspect-history
And, a final check that everything worked as expected
git log --graph --oneline --all
* fc527c5 (HEAD -> main) Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Continue with Exercise 3
Exercise 3 - Sharing changes
In this exercise, you will learn how to work with a remote repository. You will create a GitLab project, push your project to it and pull changes from the remote to your local project.
Create a GitLab project
- Log into your GitLab account
- Click the
+
button in the middle of the top bar and selectNew project
- Select
Create blank project
- Fill the text field
Project name
withgit-workshop
- Leave everything else as is and click
Create project
at the bottom of the page
You now have an empty private project. However, there are some useful instructions how to proceed. Only the last section is relevant for us (Push an existing Git repository, partially). Settings of the first sections were made in the first exercise (Git global setup).
Push your repository
From the last section (Push an existing Git repository), we ignore the first two lines. We set the remote for our repository
git remote add origin https://git.ufz.de/<you>/git-workshop.git
Finally, we push our branch main
to the remote repository
git push --set-upstream origin main
Output
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Delta compression using up to 8 threads
Compressing objects: 100% (17/17), done.
Writing objects: 100% (19/19), 2.68 KiB | 915.00 KiB/s, done.
Total 19 (delta 4), reused 0 (delta 0), pack-reused 0
To https://git.ufz.de/mlange/git-workshop.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
At this point, Git will ask for your login and password. Use your normal UFZ login here.
When completed, refresh your project's page. You will see some statistics, a list of your project files, and a nicely rendered version of README.md
.
Finally, we check the graph
git log --graph --oneline --all
Output
* fc527c5 (HEAD -> main, origin/main) Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Notice that there is now a branch origin/main
, in addition to main
. Both point to the same commit.
Pull changes
We will simulate changes made by others by editing file README.md
online.
In the file list, click README.md
. Click the blue edit
button above the text. Make a change to the file, e.g. by adding a brief description
# Git Workshop
Notes taken in the OESA Git workshop.
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* [Amending commits](amending.md)
At the top of the page, there is a Preview tab where you can check that your changes render as expected.
Scroll to the bottom of the page and click Commit changes
(you may want to change the commit message, too).
To make Git notice remote changes, we need to "fetch"
git fetch
Output
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 457 bytes | 57.00 KiB/s, done.
From https://git.ufz.de/.../git-workshop
fc527c5..f39b285 main -> origin/main
Check the graph again to see what happened
git log --graph --oneline --all
Output
* f39b285 (origin/main) Update README.md
* fc527c5 (HEAD -> main) Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Branch origin/main
is now one commit ahead of our local main
. To update the local branch, we need to pull
git pull
Output
Updating fc527c5..f39b285
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
Check the graph again
git log --graph --oneline --all
Output
* f39b285 (HEAD -> main, origin/main) Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Now, origin/main
and main
point to the same commit again.
Continue with Exercise 4
Exercise 4 - Collaborate using GitLab
In this exercise, you will learn how to use the most essential collaboration features of GitLab. You will create and manage issues and create, discuss and finalize a Merge Request.
- Create an issue
- Manage issues with boards
- Create a merge request
- Discuss changes
- Resolve threads
- Preview a branch
- Amend last commit
- Resolve the merge request
- Update local repository
Create an issue
- On your project's GitLab page, click
Issues
in the navigation at the left - Click
New issue
at the bottom of the page - Fill fields
Title
andDescription
with some content
Title
Better description in README.md
Description
Add a more informative description in file `README.md`
* [ ] What is the project about
* [ ] How to use the project
Check the Preview tab of the description field. Click Submit issue
when you are fine with the content of the preview.
You should now see the page of the issue. There are several actions available at the right, and there is a text field at the bottom to start a discussion about the issue.
Manage issues with boards
In the left navigation, under Issues
, click Boards
. A Kanban board with your issue in column Open
will appear.
To create more lists, in addition to Open
and Closed
, click Add list
(top right), and select Create project label
. Enter In Progress
as name, select a color and scroll down to click Create
.
Drag the issue to column In Progress
. This wil automatically label the issue with In Progress
. In the left navigation, under Issues
, click List
to see that the issue is labelled now.
Create a merge request
We will now fix the issue on a new branch and create a merge request for the fix.
Create and switch to a new branch better-description
git switch -c better-description
Edit file README.md
by replacing its content with
# Git Workshop
Notes taken in the OESA Git workshop in early 2021.
Use the project by browsing the files linked below, and by trying the commands listed there.
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* [Amending commits](amending.md)
Commit as usual
git status
git diff
git add README.md
git commit -m "enhanced description in README.md"
Push the branch to the GitLab project
git push --set-upstream origin better-description
Output
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 760 bytes | 760.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for better-description, visit:
remote: https://git.ufz.de/mlange/git-workshop/-/merge_requests/new?merge_request%5Bsource_branch%5D=better-description
remote:
To https://git.ufz.de/mlange/git-workshop.git
* [new branch] better-description -> better-description
Branch 'better-description' set up to track remote branch 'better-description' from 'origin'.
Go back to your project's GitLab page and refresh it. At the very top, there is a notification that you just pushed branch better-description
, with a button Create merge request
. Click that button.
You will see a form that looks very similar to the issue form. Fill the description with some informative content.
Enhanced description according issue #1.
Fixes #1.
Check the Preview, and click Submit merge request
.
Scan through the merge request's page. Also check the tabs Commits
and Changes
, right below the heading.
Discuss changes
In tab Changes
you can comment on individual lines. In the right half (the new version), hover over line 5. Left of the line, a small speech bubble icon will appear. Click it!
Enter a comment in the appearing text field, e.g.
We could add that the commands are Git commands.
Press Add comment now
. Go back to the Overview
tab. Notice the 1 unresolved thread
next to the heading. Click the speech bubble with the arrow next to it to jump to the thread. Below your comment is a text box for others to reply.
Resolve threads
We will resolve the discussion by changing file README.md
again. Open it locally with a text editor and replace the content with
# Git Workshop
Notes taken in the OESA Git workshop in early 2021.
Use the project by browsing the files linked below, and by trying the git commands listed there.
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* [Amending commits](amending.md)
Check diffs and commit as usual
git status
git diff
git add README.md
git commit -m "added note that the commands are git commands"
Push again. Now that the branch was pushed and the upstream repository was set with --set-upstream origin
, we can use a shorter form
git push
Preview a branch
You can also preview the rendered version of the branch. Go to the project's main page by clicking git-workshop
on the very top left.
Below ths statistics, there is a dropdown with main
. Click it and select better-description
. The page now shows the version on your branch.
If you scroll down and check the content, you may notice that we have a typo there. Git should be capitalized!
Amend last commit
Open file README.md
locally and fix the typo.
Inspect and stage changes
git status
git diff
git add README.md
git status
As this is a tiny change belonging to the previous commit, we amend this time
git commit --amend
Close the popup message editor.
We can now push again
git push
Output
To https://git.ufz.de/mlange/git-workshop.git
! [rejected] better-description -> better-description (non-fast-forward)
error: failed to push some refs to 'https://git.ufz.de/mlange/git-workshop.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Oops, red text! You should always read Git's messages carefully! It says that "Updates were rejected because the tip of your current branch is behind its remote counterpart". Let's check the status, maybe this helps us
git status
Output
On branch better-description
Your branch and 'origin/better-description' have diverged,
and have 1 and 1 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
nothing to commit, working tree clean
It tells us that "Your branch and 'origin/better-description' have diverged, and have 1 and 1 different commits each, respectively." We can better see what is meant here by viewing the graph
git log --graph --oneline --all
Output
* 8226777 (HEAD -> better-description) added note that the commands are git commands
| * 89a8e14 (origin/better-description) added note that the commands are git commands
|/
* 39d2543 enhanced description in README.md
* f39b285 (origin/main, main) Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
The error message as well as git status
suggest that we should pull, but that is not what we want. Instead, we have to force-push here with option --force-with-lease
git push --force-with-lease
There is also the shorter option
--force
, but it is strongly discouraged to use it as it can be destructive if a collaborator (or you) already committed on top of the amended commit.
Refresh the repository's page (still on branch better-description
) to see that the fix is there.
Resolve the merge request
Go back to the merge request's page and jump or scroll to the unresolved thread. Then, either
- Press button
Resolve thread
, or - Write something into the text box directly beneath (!) your first comment, tick
Resolve thread
, and pressAdd comment now
Now, all threads are resolved. Scroll up to the green Merge
button and press it to merge the branch into main
.
Update local repository
Fetch the changes from the remote with option --prune
to prune the merged and automatically deleted remote branch
git fetch --prune
Switch to branch main
and pull it
git switch main
git pull
Check the graph
git log --graph --oneline --all
Output
* a3d243a (HEAD -> main, origin/main) Merge branch 'better-description' into 'main'
|\
| * 8226777 (better-description) added note that the commands are git commands
| * 39d2543 enhanced description in README.md
|/
* f39b285 Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Delete the local branch better-description
, which is not required anymore
git branch --delete better-description
Check the graph again
git log --graph --oneline --all
Continue with Exercise 5
Exercise 5 - Ignoring files
In this exercise, you will learn how to make Git ignore certain files. You will convert your Markdown files into a HTML file and write a .gitignore
file to ignore it.
Generate a HTML page
You may want to generate an all-in-one document of your notes to send it to a friend, or simply to see how it looks like in its rendered form. We will do that using Pandoc.
First, create a sub-folder documents
mkdir documents
Next, we convert all Markdown files into a single HTML file
pandoc README.md linear-workflow.md inspecting.md amending.md -o documents/README.html
Navigate into folder documents
using the explorer and view the output.
We could now commit the document. However, it is good practice to not commit anything that can be generated from the project's sources. This applies also to compiled binaries, like your model's .exe
file.
But let's check the status first
git status
Output
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
documents/
nothing added to commit but untracked files present (use "git add" to track)
which should show documents/
as unstaged.
Ignore files
One way to not commit a file it not to stage it. But there is a better way provided by Git: .gitignore
files.
At the top level of your project (i.e. in git-workshop
), create a file .gitignore
(notice the dot! 1).
echo.> .gitignore
Open the file in your text editor. Here, we can list files, directories or file name patterns to be ignored, one entry per line. We will ignore the entire documents
folder. Fill the file with the following content
/documents/
For details on how to ignore directories, files, patterns etc. see the gitignore documentation.
Check the status again
git status
Output
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
nothing added to commit but untracked files present (use "git add" to track)
The file .gitignore
is listed as unstaged, but documents/
disappeared, which is exactly what was our aim.
We can now commit as usual, and also push
git add .gitignore
git status
git commit -m "added gitignore file to ignore documents"
git push
and view the graph again
git log --graph --oneline
Output
* 2b94010 (HEAD -> main, origin/main) added gitignore file to ignore documents
* a3d243a Merge branch 'better-description' into 'main'
|\
| * 8226777 added note that the commands are git commands
| * 39d2543 enhanced description in README.md
|/
* f39b285 Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Continue with Exercise 6
The leading dot is a naming convention for hidden files.
Exercise 6 - Tags for reproducibility
In this exercise, you will learn how use tags. You will create tags, push them to the remote repository and inspect them.
Create tags
We want to add two tags, one to the commit before our merge request, and one to the current state.
View the graph to get the hash of the commit we want to tag first
git log --graph --oneline --all
Output
* 2b94010 (HEAD -> main, origin/main) added gitignore file to ignore documents
* a3d243a Merge branch 'better-description' into 'main'
|\
| * 8226777 added note that the commands are git commands
| * 39d2543 enhanced description in README.md
|/
* f39b285 Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Then, we add a tag v0.1.0
to that commit
git tag v0.1.0 f39b285
Tagging the current commit is even simpler
git tag v0.1.1
View the graph again
git log --graph --oneline --all
Output
* 2b94010 (HEAD -> main, tag: v0.1.1, origin/main) added gitignore file to ignore documents
* a3d243a Merge branch 'better-description' into 'main'
|\
| * 8226777 added note that the commands are git commands
| * 39d2543 enhanced description in README.md
|/
* f39b285 (tag: v0.1.0) Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
Push tags
We now have two tags, but they are only local. Push all tags to the remote
git push --tags
Output
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To https://git.ufz.de/mlange/git-workshop.git
* [new tag] v0.1.0 -> v0.1.0
* [new tag] v0.1.1 -> v0.1.1
Inspect tags
To view a list of all tags, use
git tag
Output
v0.1.0
v0.1.1
Individual tags can be inspected with git show
, just like commits
git show v0.1.0
git show v0.1.1
The output should look like when showing a commit.
Continue with Exercise 7
Exercise 7 - Keep branches up-to-date
In this exercise, you will learn how to keep branches up-to-date with changes made by collaborators (or yourself). You will back-merge branch main
into a topic branch.
- Make changes on a branch
- Simulate changes by a collaborator
- Pull the changes
- Back-merge into your branch
Make changes on a branch
We continue our work on taking notes, again on a separate branch. Create and switch to a new branch branching
and check the result
git switch -c branching
git branch
Create a new file branching.md
echo.> branching.md
Fill it with
# Branching
## Create a new branch
```
git branch inspect-history
git switch inspect-history
git branch
```
Link the file in README.md
# Git Workshop
Notes taken in the OESA Git workshop in early 2021.
Use the project by browsing the files linked below, and by trying the Git commands listed there.
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* [Amending commits](amending.md)
* [Branching](branching.md)
Then, commit as usual
git status
git diff
git add README.md branching.md
git status
git commit -m "added page on branching"
Simulate changes by a collaborator
Meanwhile, a collaborator (or you) may have made changes to branch main
, e.g. by merging a Merge Request. We simulate that by making an online edit.
Go to your project's page and edit REAMDE.md
. Add a final note
# Git Workshop
Notes taken in the OESA Git workshop in early 2021.
Use the project by browsing the files linked below, and by trying the Git commands listed there.
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* [Amending commits](amending.md)
For further information, see the [OESA Git Workshop book](https://oesa.pages.ufz.de/git-exercises).
Preview and commit your changes on target branch main
(should be already set).
Pull the changes
Pull the changes into your local repository
git switch main
git pull
Then, check the graph
git log --graph --oneline --all
Output
* 653207e (HEAD -> main, origin/main) Update README.md
| * 3e445bb (branching) added page on branching
|/
* 2b94010 (tag: v0.1.1) added gitignore file to ignore documents
* a3d243a Merge branch 'better-description' into 'main'
|\
| * 8226777 added note that the commands are git commands
| * 39d2543 enhanced description in README.md
|/
* f39b285 (tag: v0.1.0) Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
As expected, main
has diverged.
Back-merge into your branch
Before you continue your work on branch branching
, you may want to update it to the latest state of main
. Do that by merging main
into branching
git switch branching
git merge main
There is a conflict in README.md
again, but you already know how to resolve it. Open the file locally and recolve the conflict. The result should look like this
# Git Workshop
Notes taken in the OESA Git workshop in early 2021.
Use the project by browsing the files linked below, and by trying the Git commands listed there.
Content
* [Linear workflow](linear-workflow.md)
* [Inspecting](inspecting.md)
* [Amending commits](amending.md)
* [Branching](branching.md)
For further information, see the [OESA Git Workshop book](https://oesa.pages.ufz.de/git-exercises).
Then, commit as usual
git status
git diff
git add README.md
git status
git commit
As before, close the editor popup to complete the commit.
Finally, inspect the graph again
git log --graph --oneline --all
* e8ed3fd (HEAD -> branching) Merge branch 'main' into branching
|\
| * 653207e (origin/main, main) Update README.md
* | 3e445bb added page on branching
|/
* 2b94010 (tag: v0.1.1) added gitignore file to ignore documents
* a3d243a Merge branch 'better-description' into 'main'
|\
| * 8226777 added note that the commands are git commands
| * 39d2543 enhanced description in README.md
|/
* f39b285 (tag: v0.1.0) Update README.md
* fc527c5 Merge branch 'inspect-history'
|\
| * eba0f8f added page on inspecting the history
* | e25d3cc Merge branch 'amending-commits'
|\ \
| |/
|/|
| * 0639ed4 added page on amending commits
|/
* 1860049 added linear workflow
* d8d9072 initial commit
This starts to look a bit confusing. Here is an alternative visualization that better conveys what really happened
╭>○ e8ed3fd (HEAD -> branching) Merge branch 'main' into branching
● │ 653207e (main, origin/main) Update README.md
│ ● 3e445bb added page on branching
├─╯
● 2b94010 [v0.1.1] added gitignore file to ignore documents
○<╮ a3d243a Merge branch 'better-description' into 'main'
│ ● 8226777 added note that the commands are git commands
│ ● 39d2543 enhanced description in README.md
├─╯
● f39b285 [v0.1.0] Update README.md
○<──╮ fc527c5 Merge branch 'inspect-history'
○<╮ │ e25d3cc Merge branch 'amending-commits'
│ ● │ 0639ed4 added page on amending commits
├─╯ ● eba0f8f added page on inspecting the history
├───╯
● 1860049 added linear workflow
● d8d9072 initial commit
This visualization was created with git-graph. For an interactive version that also allows you to view commits, diffs, etc. see git-igitt.
How to continue
This chapter provides some links and recommendations on how to continue using and learning Git.
Further reading
Some reading suggestions to continue with:
- The official Git Documentation
- Chris Beams: How to Write a Git Commit Message
- Martin Fowler: Patterns for Managing Source Code Branches
- Vincent Driessen: A successful Git branching model (Git-Flow)
Recommended GUI clients
For those who prefer to work with a GUI client rather than the command line:
- Sourcetree is a freeware GUI client for Windows & MacOS.
- Some text editors like Atom and many IDEs like IntelliJ and Eclipse have a Git integration or plugin.
- git-igitt is a TUI client for browsing the history in the console.
The Git documentation provides an extensive list of GUI clients.
Git forges
Git forges are online platforms where you can host repositories, and get a lot of other features for project management and collaboration.
UFZ
Use the UFZ GitLab for your work-related projects. Non-UFZ collaborators can get an account there, just contact the WKDV.
Don't put your personal/hobby projects there, as they will then be owned by the UFZ.
Other
The most famous platforms to use for online repositories:
- On GitLab.com, you get the same features as with the UFZ GitLab instance. They offer a free plan with unlimited public and private repositories.
- GitHub is the most famous Git forge out there. If you want to find contributors to your projects, you probably have the best chance there. It has similar features like GitLab, and also offers a free plan.
Both GitHub and GitLab offer all features you need for your projects, from merge requests over issue trackers and wikis to Continuous Integration. For a comparison between GitHub and GitLab, see e.g. this blog post.
CheatSheet Command Line
Command | Effect | Examples |
---|---|---|
dir
|
List directory content |
dir
dir *.md
|
cd <dir>
|
Navigate into directory |
cd Projects
|
cd ..
|
Navigate to parent directory | |
mkdir <dir>
md <dir>
|
Create a directory |
mkdir git-workshop
|
help
help <cmd>
|
Get help (for a command) |
help mkdir
|
<cmd> > <file>
|
Redirect output to file |
dir > out.txt
echo Hello World > out.txt
|
<cmd> >> <file>
|
Redirect (append) output to file |
dir >> out.txt
|
type <file>
|
Display the content of a file |
type README.md
|
start <file>
|
Start a program or open a file |
start notepad
start README.md
|
Ctrl+C
|
Exit/abort the current program | |
Up/Down Arrows | Scroll through previous command |
CheatSheet Git Commands
Command | Effect | Examples |
---|---|---|
init
|
Initialize a local repo |
git init
|
clone
|
Clone a remote repo |
git clone https://git.ufz.de/oesa/git-exercises.git
|
status
|
View the repo status |
git status
|
show
|
Show different things |
git show
git show v0.1.0
git show 3cda487
|
diff
|
View diffs |
git diff
git diff README.md
git diff 3cda487 c8b0455
|
log
|
Show the repo's history |
git log
git log --all
git log --graph --oneline --all
|
add
|
Stage files |
git add README.md
git add *.md
git add --all
|
reset
|
Un-stage files |
git reset README.md
git reset --all
|
commit
|
Commit staged changes |
git commit
git commit -m "A commit message"
git commit --amend
|
checkout
|
Checkout, e.g. branch |
git checkout main
|
branch
|
List, create, delete branches |
git branch
git branch my-feature
git branch --delete my-feature
|
merge
|
merge branch into current branch |
git merge my-feature
git merge my-feature --no-ff
|
fetch
|
Get remote changes |
git fetch
|
pull
|
Pull changes from remote |
git pull origin main
git pull --all
|
push
|
Push something to remote |
git push -u origin main
git push --tags
|
tag
|
List and create tags |
git tag
git tag v0.1.0
git tag v0.1.0 f3c5a77
|