This is a practical workshop consisting of common Git-related actions.
It is based on the unikraft/catalog-core
repository, giving us a concrete Git repository to screw up ... hmmmm ... to do wonderful amazing great things to.
First of all, clone the repository:
git clone https://github.com/rosedu/workshop-git
cd workshop-git/
And let's get going! 🚀
-
See the current branch and status:
git status
-
See local branches:
git branch
-
See local and remote branches:
git branch -a
-
Check out remote branches locally:
git branch base origin/base git branch scripts origin/scripts
-
Show verbose information about branches:
git branch -vv git branch -vv -a
-
Check out to a local branch:
git checkout base ls git checkout scripts ls git checkout main
-
List contents of another branch without checking out:
git ls-tree scripts git ls-tree scripts:c-fs git ls-tree scripts:c-fs/rootfs git ls-tree scripts --name-only git ls-tree scripts:c-fs --name-only git ls-tree scripts:c-fs/rootfs --name-only git ls-tree -r scripts --name-only
The construct
scripts:c-fs
means thec-fs
filesystem entry in thescripts
branch. Similarly, the constructscripts:c-fs/rootfs
means thec-fs/rootfs
filesystem entry in thescripts
branch. -
Show contents of file on another branch without checking out:
git show scripts:c-fs/build.qemu.x86_64 git show scripts:c-fs/README.scripts.md
-
Do more listing. Try out the other commands here.
-
Check out the
test
branch from the remoteorigin/test
branch. List contents, check out the branch, get back to themain
branch.
-
Make sure you are on the
main
branch:git checkout main git status
-
List commit history:
git log git log base git log --oneline base git log --pretty=fuller
-
Show top commit contents:
git show git show HEAD
-
Show commit contents by commit ID:
git show 1a02ae3
-
Only show actual contents, no metadata:
git show --pretty="" 1a02ae3
-
Only show modified files:
git show --pretty="" --name-only 1a02ae3
-
Show commits that modified a file:
git checkout base git blame README.md git checkout main
-
Show commits that modified a path:
git log scripts -- README.md git log scripts -- c-fs
-
Show difference between two commits / references:
git diff base scripts
-
Show commit difference between two references:
git cherry -v main scripts git cherry -v scripts main git cherry -v main d379011 git cherry -v d379011 main
-
How are the three branches (
base
,scripts
,test
) constructed? Which is constructed on top of the other? -
Do more history inspection.
-
If not already configured, configure your name and e-mail:
git config --global user.name "<your-full-name-here>" git config --global user.email "<your-email-here>"
Use your full name as you would typically do:
Firstname Lastname
. -
Configure colored output:
git config --global color.ui "auto"
-
Configure aliases:
git config --global alias.lg 'log --pretty=fuller' git lg
-
Check the configuration:
cat .git/config cat ~/.gitconfig
We make mistakes:
- We create commits we shouldn't have (yet) created.
- We leave changes out of commits.
- We amend the wrong commit.
- We do merges / rebases / cherry-picks that fail.
- We add a change in the staging area that we shouldn't have (yet) added.
- We delete a file by mistake.
These things happen. We solve them. We just need to know how to do that.
-
First prepare a messed up environment, by running:
./mess-it-up.sh
-
Now look at the mess:
git status
-
See the commit history:
git log
See the
bla bla
commit (latest). And see the wrong message (Bue
instead ofBye
) for the other other commit. -
Note: If, at any point in time, you miss a command, or something bad simply happened, reset the environment by running:
./reset-all.sh
The go back to step 1 and prepare the messed up environment again.
-
Let's first get rid of all the temporary files we do not require (they were added by mistake):
git clean -d -f git status
-
Restore the deleted
Makefile
:git status git restore c-hello/Makefile git status
-
Restore the staged deleted
hello.c
:git status git restore --staged c-hello/hello.c git status git restore c-hello/hello.c git status
-
Restore the staged new file
c-bye/build.fc.x86_64
to create a proper commit:git status git restore c-bye/build.fc.x86_64 git status
-
See the commit history again:
git log
-
Remove the
bla bla
commit:git reset HEAD^ git status git log rm blabla.txt
-
Update the commit message from
Bue
toBye
:git log git commit --amend # do edit as required git log git show
-
Create a new commit with the
c-bye/build.fc.x86_64
file:git add c-bye/build.fc.x86_64 git commit -s -m 'c-bye: Add Firecracker build script for x86_64' git log git show git status
-
Repeat the above steps at least 2 more times.
Aim to have one time without checking the instructions. That is, run the
./mess-it-up.sh
script and then repair the mess by yourself.If, at any point, you get lost, run the reset script:
./reset-all.sh
-
Do your own messing up of the environment. Go to a given branch, remove files, create new files, create commits, add files to staging area etc. Then repair the environment.
If, at any point, you get lost, run the reset script:
./reset-all.sh
Let's get to a situation where we need to repair the commit history. We will have a setup where we have the following stack of commits:
- (top) correct commit
- (next) commit that shouldn't exist (
bla bla
commit) - (next-next) commit with a typo (
Bue
instead ofBye
)
We want to edit the commit history and:
- Remove the
bla bla
commit. - Fix the typo.
-
Create the setup:
./set-up-history-edit.sh git status git log
-
Note: If, at any point in time, you miss a command, or something bad simply happened, reset the environment by running:
./reset-all.sh
The go back to step 1 and prepare the setup for commit history editing.
-
Go into commit history editing mode:
git rebase -i HEAD~3
You get an editor screen with an output like this:
pick e5442f0 Add C Bue application pick 06eb1fa bla bla pick 74f3d3e c-bye: Add Firecracker build script for x86_64
-
Edit the rebase screen contents in order to edit the commit with the typo (
Bue
instead ofBye
) and to drop the extra commit (the one withbla bla
). Have the editor screen have the contents:edit e5442f0 Add C Bue application drop 06eb1fa bla bla pick 74f3d3e c-bye: Add Firecracker build script for x86_64
That is, the first line (the bad commit message) should have
edit
instead ofpick
- we edit the commit. And the second line (the extra commit) should havedrop
instead ofpick
- we drop the commit.Save the editor screen.
-
We are currently editing the typo commit:
git log git show
-
Update the commit message from
Bue
toBye
:git log git commit --amend # do edit as required git log git show
-
Continue the commit history editing:
git rebase --continue
-
The extra commit has been dropped:
git log git status
-
The commit history editing (aka the rebase) is done:
git rebase --continue
It says "No rebase in progress?", meaning the rebase is done.
-
Repeat the above steps at least 2 more times.
Aim to have one time without checking the instructions. That is, run the
./set-up-history-edit.sh
script and then repair the commit history by yourself.If, at any point, you get lost, run the reset script:
./reset-all.sh
-
Do your own commit history that you want to edit. Go to a given branch, create commits, create some bad or extra commits. Then repair the commit history.
If, at any point, you get lost, run the reset script:
./reset-all.sh
We will get some new content that we will add as commits to the repository.
Make sure you are on the main
branch and everything is clean:
git checkout main
Or, reset the repository:
./reset-all.sh
-
Create contents from archive:
unzip support/c-bye.zip git status
We now have a
c-bye/
directory:ls c-bye/
There are a lot of files. We want to add them as 3 separate commits in 3 separate branches.
- The
bye.c
,Makefile
,Makefile.uk
,fc...
,xen...
,README.md
files will go to thebase
branch. - The
defconfig...
,build...
,run...
,README.scripts.md
files will go to thescripts
branch. - The
test...
files will go to thetest
branch.
- The
-
Go to the
c-bye/
directory:cd c-bye/ ls
Let's create commit to base
branch:
-
Check out the
base
branch:git checkout base
-
Add contents to staged area:
git add bye.c Makefile Makefile.uk README.md xen.* fc.* .gitignore git status
-
Create the commit:
git commit -s -m 'Introduce C Bye on Unikraft'
-
List the commit:
git log git show
-
Look at the commit for the initial C Hello program:
git show 7fd6e9290dddc2ae799ae5df684668a7d16e87f3
The commit message is:
Introduce C Hello on Unikraft Add `c-hello/` directory: - `hello.c`: the source code file - `Makefile.uk`: defining the source code files used - `Makefile`: for building the application - `fc.x86_64.json` / `fc.arm64.json`: Firecracker configuration - `xen.x86_64.cfg` / `xen.arm64.cfg`: Xen configuration - `README.md`: instructions - `.gitignore`: ignore generated files
We want something similar for our C bye commit.
-
Update the commit message by amending:
git commit --amend
You get an editable screen. Edit the commit message to have contents similar to the one for C Hello. Use copy-paste.
You can use
git commit --amend
to constantly update the commit.See the final result with:
git log git show
Let's create commit to scripts
branch:
-
Check out the
scripts
branch:git checkout scripts
-
Add contents to staged area:
git add defconfig.* build.* run.* README.scripts.md git status
-
Create the commit:
git commit -s -m 'c-bye: Add scripts'
-
List the commit:
git log git show
-
Look at the commit for the initial C Hello program:
git show 04cf0f57f2853d73a5c25082d4652fef63da8f57
The commit message is:
c-hello: Add scripts Use scripts as quick actions for building and running C Hello on Unikraft. - `defconfig.<plat>.<arch>`: default configs, used by build scripts - `build.<plat>.<arch>`: scripts for building Unikraft images - `run.<plat>.<arch>`: scripts for running Unikraft images - `README.script.md`: companion README with instructions
We want something similar for our C bye commit.
-
Update the commit message by amending:
git commit --amend
You get an editable screen. Edit the commit message to have contents similar to the one for C Hello. Use copy-paste.
You can use
git commit --amend
to constantly update the commit.See the final result with:
git log git show
Let's create commit to test
branch:
-
Check out the
test
branch:git checkout test
-
Add contents to staged area:
git add test* git status
-
Create the commit:
git commit -s -m 'c-bye: Add test scripts'
-
List the commit:
git log git show
-
Reset the configuration:
./reset-all.sh
-
Repeat the above steps at least 2 more times.
Aim to have one time without checking the instructions. That is, create the 3 commits in the 3 branches for C bye.
If, at any point, you get lost, run the reset script:
./reset-all.sh
-
Do the same for the C++ Bye program.
Make sure you are on the
main
branch:git status git checkout main
First unpack the contents:
unzip support/cpp-bye.zip git status
We now have a
cpp-bye/
directory:ls cpp-bye/
There are a lot of files. We want to add them as 3 separate commits in 3 separate branches.
- The
bye.cpp
,Makefile
,Makefile.uk
,Config.uk
,fc...
,xen...
,README.md
files will go to thebase
branch. - The
defconfig...
,build...
,run...
,README.scripts.md
files will go to thescripts
branch. - The
test...
files will go to thetest
branch.
Follow the steps for C Bye to create the commits for C++ Bye.
- The
-
Do the same for the Python Bye program.
Make sure you are on the
main
branch:git status git checkout main
First unpack the contents:
unzip support/python3-bye.zip git status
We now have a
python3-bye/
directory:ls python3-bye/
There are a lot of files. We want to add them as 3 separate commits in 3 separate branches.
- The
bye.py
,Makefile
,Makefile.uk
,Config.uk
,fc...
,xen...
,README.md
files will go to thebase
branch. - The
defconfig...
,build...
,run...
,README.scripts.md
files will go to thescripts
branch. - The
test...
files will go to thetest
branch.
Follow the steps for C bye to create the commits for Python3 Bye.
- The
At this point there are commits in the base
branch that are not part of the scripts
branch.
And there are commits in the scripts
branch that are not part of the test
branch.
We aim to have the scripts
branch built on top of the base
branch.
And we want to have the test
branch built on top of the scripts
branch.
For this, all commits from the base
branch will have to be on the scripts
branch.
And all commits from the scripts
branch will have to be on the test
branch.
-
To get the
c-bye
commit from thebase
branch to thescripts
branch, first check out thescripts
branch:git checkout scripts
-
Find out the commit ID in the
base
branch:git log base
Scroll the commit history and copy the commit ID belonging to the
c-bye
program. That is, the ID of the commit you created earlier with the message:Introduce C Bye on Unikraft
. -
Use the commit ID cherry pick the commit from the
base
branch to thescripts
branch:git cherry-pick <commit-id>
Replace
<commit-id>
with the commit ID you copied above (copy & paste). -
Check the updated history of the
scripts
branch:git log
-
To get the
c-bye
commits from thescripts
branch to thetest
branch, first check out thetest
branch:git checkout test
-
First chery pick the the
base
commit that is now onscripts
:git cherry-pick <commit-id>
This is the same commit ID from above.
-
Now let's get the
c-bye
commit from thescripts
branch. Find out the commit ID in thescripts
branch:git log scripts
Scroll the commit history and copy the commit ID belonging to the
c-bye
program. That is, the ID of the commit you created earlier with the message:c-hello: Add scripts
. -
Use the commit ID cherry pick the commit from the
scripts
branch to thetest
branch:git cherry-pick <new-commit-id>
Replace
<new-commit-id>
with the commit ID you copied above (copy & paste). -
Check the updated history of the
scripts
branch:git log
Note: If, at any point, you did something wrong, recall that you can drop the top commit by doing:
git reset --hard HEAD^
-
Repeat the above steps at least 2 more times.
Aim to have one time without checking the instructions. That is, have the
scripts
based on thebase
branch, and have thetest
branch based on thescripts
branch.For starters, drop the newly cherry-picked commit from the
scripts
branch:git checkout scripts git reset --hard HEAD^
And drop the newly cherry-picked commits from the
test
branch:git checkout test git reset --hard HEAD^^
Now repeat the steps above.
-
Do the same steps for the C++ Bye program. That is, have the
scripts
based on thebase
branch, and have thetest
branch based on thescripts
branch. -
Do the same steps for the Python Bye program. That is, have the
scripts
based on thebase
branch, and have thetest
branch based on thescripts
branch.
At this point, the scripts
branch is based on the base
branch.
And the test
branch is based on the scripts
branch.
What we do not like, however, is that the commits in the scripts
and the test
branch are not in the correct order.
In the scripts branch the commits are (top-to-bottom):
- python3-bye: Add scripts
- Introduce Python3 Bye
- cpp-bye: Add scripts
- Introduce C++ Bye
- c-bye: Add scripts
- Introduce C Bye
- python3-bye: Add test scripts
- cpp-bye: Add test scripts
- c-bye: Add test scripts
Use git log
to confirm this:
git log
git log --oneline
The order we want is (top-to-bottom):
- python3-bye: Add test scripts
- python3-bye: Add scripts
- Introduce Python3 Bye
- cpp-bye: Add test scripts
- cpp-bye: Add scripts
- Introduce C++ Bye
- c-bye: Add scripts
- Introduce C Bye
- c-bye: Add test scripts