8. When do I get an advantage from git and bash?#
8.1. What is a GPG signature?#
It’s a way of assuring anyone viewing commits on GitHub tht those commits came from known, safe sources
There are ways to configure the signature locally so that local commits are signed and verified. This is an extra way for collaborators to secure that the commit was made by the person they know and are working with and not someone else.
8.2. When do I get an advantage from git and bash?#
so far we have used git and bash to accomplish familiar goals, and git and bash feel like just extra work for familiar goals.
Today, we will start to see why git and bash are essential skills: they give you efficiency gains and time traveling super powers (within your work, only, sorry)
8.3. Important references#
Use these for checking facts and resources.
8.4. Setup#
First, we’ll go back to our github inclass folder
cd Documents/systems/github-inclass-AymanBx/
And confirm we are where we want to be
pwd
/c/Users/Ayman/Documents/systems/github-inclass-AymanBx/
and make sure we are up to date:
git status
$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
We checked if there were any uncommited/unstaged changes that happened locally
How do we check for changes that occured online?
Then we will use fetch to see if we are really up to date
git fetch
And let’s check again to confirm
git status
$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
Let’s check for existing prs in the repo
Find your PR that I opened for you today that has the title, “2/20 in class activity”
Note this is optional, and only works with the gh
cli is installed
gh pr list
Showing 1 of 1 open pull requests in compsys-progtools/gh-inclass-AymanBx
#4 Feb 20 in class activity organizing_ac about 2 hours ago
gh pr view
Feb 20 in class activity #3
Open • AymanBx wants to merge 1 commit into main from organizing_ac • about 2 hours ago
+17 -0 • No checks
this draft PR https://github.blog/2019-02-14-introducing-draft-pull-requests/ adds some example files that we will use
during class on 9/19. \n\n wait until class time (or when you make up class by following the notes) to do anything
with this PR
View this pull request on GitHub: https://github.com/compsys-progtools/gh-inclass-AymanBx/pull/3
Since there only is one pr in your repo (most of you) it will show you details of that pr (Title, body, etc.)
If that doesn’t work try using the number shown next to the pr when we listed the prs
gh pr view #3
Feb 20 in class activity #3
Open • AymanBx wants to merge 1 commit into main from organizing_ac • about 2 hours ago
+17 -0 • No checks
this draft PR https://github.blog/2019-02-14-introducing-draft-pull-requests/ adds some example files that we will use
during class on 9/19. \n\n wait until class time (or when you make up class by following the notes) to do anything
with this PR
View this pull request on GitHub: https://github.com/compsys-progtools/gh-inclass-AymanBx/pull/3
Next get the files for today’s activity:
Find your PR that I opened for you today that has the title, “2/20 in class activity”
Mark it ready for review to change from draft
Merge it
Let’s open the PR in the browser:
gh repo view --web
Opening github.com/intcompsys-progtools/github-inclass-AymanBx in your browser.
and merge them there.
To get added to your main branch.
Let’s make sure we’re on main
git checkout main
Now we bring the files to the local repo:
git fetch
remote: Enumerating objects: 20, done.
remote: Counting objects: 100% (20/20), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 19 (delta 0), reused 18 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (19/19), 2.55 KiB | 84.00 KiB/s, done.
From https://github.com/compsys-progtools/gh-inclass-AymanBx
162a47b..581ac5e main -> origin/main
* [new branch] organizing_ac -> origin/organizing_ac
And let’s check for changes
git status
On branch main
Your branch is behind 'origin/main' by 2 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
ls
README.md about.md
Notice that it updated the .git, but not our working directory.
It said Your branch is behind 'origin/main' by 2 commits
cat about.md
But git knows we are behind and tells us how to update
git pull
$ git pull
Updating 162a47b..581ac5e
Fast-forward
API.md | 1 +
CONTRIBUTING.md | 1 +
LICENSE.md | 1 +
_config.yml | 1 +
_toc.yml | 1 +
abstract_base_class.py | 1 +
alternative_classes.py | 1 +
example.md | 1 +
helper_functions.py | 1 +
important_classes.py | 1 +
philosophy.md | 1 +
scratch.ipynb | 1 +
setup.py | 1 +
tests_alt.py | 1 +
tests_helpers.py | 1 +
tests_imp.py | 1 +
tsets_abc.py | 1 +
17 files changed, 17 insertions(+)
create mode 100644 API.md
create mode 100644 CONTRIBUTING.md
create mode 100644 LICENSE.md
create mode 100644 _config.yml
create mode 100644 _toc.yml
create mode 100644 abstract_base_class.py
create mode 100644 alternative_classes.py
create mode 100644 example.md
create mode 100644 helper_functions.py
create mode 100644 important_classes.py
create mode 100644 philosophy.md
create mode 100644 scratch.ipynb
create mode 100644 setup.py
create mode 100644 tests_alt.py
create mode 100644 tests_helpers.py
create mode 100644 tests_imp.py
create mode 100644 tsets_abc.py
this message tells us what updates were made
Let’s check what we got now:
$ ls
API.md abstract_base_class.py setup.py
CONTRIBUTING.md alternative_classes.py tests_alt.py
LICENSE.md example.md tests_helpers.py
README.md helper_functions.py tests_imp.py
_config.yml important_classes.py tsets_abc.py
_toc.yml philosophy.md
about.md scratch.ipynb
8.5. Branches review#
We can get a list of the branches we have locally
git branch
and we can get help to see what options that has with git branch --help
or see them with their upstream information using the -vv
for verbose option
git branch -vv
1-create-an-about-file 9e8a8b6 [origin/1-create-an-about-file] Created an about file. Closes #1
fun_fact 8040553 Added fun fact
* main 162a47b [origin/main: behind 2] Create README.md
my_branch 8bd4ea3 Merge pull request #2 from compsys-progtools/1-create-an-about-file
8.6. Organizing a project (working with files)#
A common question is about how to organize projects. While our main focus
in this class session is the bash
commands to do it, the task that we are
going to do is to organize a hypothetical python project
Put another way, we are using organizing a project as the context to motivate practicing with bash commands for moving files.
A different the instructor might go through a slide deck that lists commands and describes what each one does and then have examples at the end. Instead, we are going to focus on organizing files, and I will introduce the commands we need along the ways.
next we are going to pretend we worked on the project and made a bunch of files
I gave a bunch of files, each with a short phrase in them.
none of these are functional files
the phrases mean you can inspect them on the terminal
Note
file extensions are for people; they do not specify what the file is actually written like
these are all actually plain text files
what command can we use to view the contents of a file named my.file
[ ] shw my.file (short for show)
[ ] prt my.file (short for print)
[x] cat my.file (short for concatenate)
[ ] dis my.file (short for display)
$ cat setup.py
file with function with instructions for pip
cat
concatenates the contents of a file to stdout, which is a special file that our terminal reads
(think about in C you can write to STDOUT or STDERR, some IDEs have separate visual panels for these two places)
create a new branch from main.
git checkout -b organization
$ git checkout -b organization
Switched to a new branch 'organization'
What advantage does making a new branch here give us?
[ ] its required for changes
[X] allows us to test things before putting them on main
[ ] it creates a beautiful tree eventually
git stauts
git: 'stauts' is not a git command. See 'git --help'.
The most similar command is
status
Typo…
git status
On branch organization
nothing to commit, working tree clean
8.7. Files, Redirects, git restore#
cat README.md
# Practice
My name is Ayman
Echo allows us to send a message to stdout.
echo "age=27"
age = 27
Let’s connect what we are about to learn to something you have probably seen before.
Think about a time you opened a file within a program that you wrote. For example
fopen
in Cor
open
in Python
in both cases one parameter is the file to open, what other parameters have you used?
Typically, when we write to a file, in programming, we also have to tell it what mode to open the file with, and some options are:
read
write
append
References
C is not an open source language in the typical sense so there is no “official” C docs But multiple companies over the years have created compilers for the C language, so they created documntation to explain the language from their prespectivce
We can redirect the contents of a command from stdout to a file in bash
. Like file operations while programming there is a similar concept to this mode.
There are two types of redirects, like there are two ways to write to a file, more generally:
overwrite (
>
)append (
>>
)
We can add contents to files with echo
and >>
$ echo "age=27" >> README.md
Then we check the contents of the file and we see that the new content is there.
cat README.md
# Practice
My name is Ayman
age = 27
let’s see what changes happened
$ git status
On branch organization
Changes not staged for commit:
(use "git add <file>..." to update what will be committd)
(use "git restore <file>..." to discard changes in workng directory)
modified: README.md
no changes added to commit (use "git add" and/or "git comit -a")
We can redirect other commands too:
git status >> curgit
Notice, We didn’t get the output from the git status
command this time
But we can see this created a new file
ls
API.md abstract_base_class.py setup.py
CONTRIBUTING.md alternative_classes.py test_alt.py
LICENSE.md ==curgit== test_help.py
README.md helper_functions.py test_imp.py
_config.yml important_classes.py tests_abc.py
about.md example.md
and we can look at its contents too
cat curgit
On branch organization
Changes not staged for commit:
(use "git add <file>..." to update what will be committd)
(use "git restore <file>..." to discard changes in workng directory)
modified: README.md
no changes added to commit (use "git add" and/or "git comit -a")
this is not a file we actually want, which gives us a chance to learn another new bash command:
rm
for remove
rm curgit
Note that this is a true, full, and complete DELETE, this does not put the file in your recycling bin or the apple trash can that you can recover the file from, it is gone for real.
We will see soon a way around this, because git can help.
use rm
with great care
Let’s confirm that it’s gone
ls
API.md abstract_base_class.py setup.py
CONTRIBUTING.md alternative_classes.py tests_alt.py
LICENSE.md example.md tests_helpers.py
README.md helper_functions.py tests_imp.py
_config.yml important_classes.py tsets_abc.py
_toc.yml philosophy.md
about.md scratch.ipynb
Now we have made some changes we want, so let’s commit our changes.
git commit -a -m 'add age to readme'
warning: in the working copy of 'README.md', LF will be rplaced by CRLF the next time Git touches it
[organization 4ccfb5f] added age to readme
1 file changed, 1 insertion(+)
git status
On branch organization
nothing to commit, working tree clean
Now, let’s go back to thinking about redirects. We saw that with two >>
we appended to the file. With just one what happens?
echo "age = 27" > README.md
We check the file now
cat README.md
age = 27
It wrote over. This would be bad, we lost content, but this is what git is for!
It is very very easy to undo work since our last commit.
This is good for times when you have something you have an idea and you do not know if it is going to work, so you make a commit before you try it. Then you can try it out. If it doesn’t work you can undo and go back to the place where you made the commit.
To do this, we will first check in with git
git status
On branch organization
Changes not staged for commit:
(use "git add <file>..." to update what will be committd)
(use "git restore <file>..." to discard changes in workng directory)
modified: README.md
no changes added to commit (use "git add" and/or "git comit -a")
Notice that it tells us what to do (use "git restore <file>..." to discard changes in working directory)
. The version of README.md that we broke is in the working directory but not commited to git, so git refers to them as “changes” in the workign directory.
$ git restore README.md
this command has no output, so we can use git status to check first
git status
On branch organization
nothing to commit, working tree clean
and it looks like it did before the >
line. and we can check the file too
$ cat README.md
# Practice
My name is Ayman
age = 27
Back how we wanted it!
Now we will add some text to the readme
echo "|file | contents |
> | --| -- |
> | abstract_base_class.py | core abstract classes for the project |
> | helper_functions.py | utitly funtions that are called by many classes |
> | important_classes.py | classes that inherit from the abc |
> | alternative_classes.py | classes that inherit from the abc |
> | LICENSE.md | the info on how the code can be reused|
> | CONTRIBUTING.md | instructions for how people can contribute to the project|
> | setup.py | file with function with instructions for pip |
> | test_abc.py | tests for constructors and methods in abstract_base_class.py|
> | tests_helpers.py | tests for constructors and methods in helper_functions.py|
> | tests_imp.py | tests for constructors and methods in important_classes.py|
> | tests_alt.py | tests for constructors and methods in alternative_classes.py|
> | API.md | jupyterbook file to generate api documentation |
> | _config.yml | jupyterbook config for documentation |
> | _toc.yml | jupyter book toc file for documentation |
> | philosophy.md | overview of how the code is organized for docs |
> | example.md | myst notebook example of using the code |
> | scratch.ipynb | jupyter notebook from dev |" >> README.md
this explains each file a little bit more than the name of it does. We see there are sort of 5 groups of files:
about the project/repository
code that defines a python module
test code
documentation
extra files that “we know” we can delete.
We also learn something about bash:
using the open quote "
then you stay inside that until you close it. when you press enter the command does not run until after you close the quotes
$ cat README.md
# Practice
My name is Ayman
age = 27
|file | contents |
> | --| -- |
> | abstract_base_class.py | core abstract classes for the project |
> | helper_functions.py | utitly funtions that are called by many classes |
> | important_classes.py | classes that inherit from the abc |
> | alternative_classes.py | classes that inherit from the abc |
> | LICENSE.md | the info on how the code can be reused|
> | CONTRIBUTING.md | instructions for how people can contribute to the project|
> | setup.py | file with function with instructions for pip |
> | test_abc.py | tests for constructors and methods in abstract_base_class.py|
> | tests_helpers.py | tests for constructors and methods in helper_functions.py|
> | tests_imp.py | tests for constructors and methods in important_classes.py|
> | tests_alt.py | tests for constructors and methods in alternative_classes.py|
> | API.md | jupyterbook file to generate api documentation |
> | _config.yml | jupyterbook config for documentation |
> | _toc.yml | jupyter book toc file for documentation |
> | philosophy.md | overview of how the code is organized for docs |
> | example.md | myst notebook example of using the code |
> | scratch.ipynb | jupyter notebook from dev |
$ ls
API.md abstract_base_class.py setup.py
CONTRIBUTING.md alternative_classes.py tests_alt.py
LICENSE.md example.md tests_helpers.py
README.md helper_functions.py tests_imp.py
_config.yml important_classes.py tsets_abc.py
_toc.yml philosophy.md
about.md scratch.ipynb
8.8. Getting organized#
First, we’ll make a directory with mkdir
mkdir docs
$ ls
API.md abstract_base_class.py scratch.ipynb
CONTRIBUTING.md alternative_classes.py setup.py
LICENSE.md docs/ tests_alt.py
README.md example.md tests_helpers.py
_config.yml helper_functions.py tests_imp.py
_toc.yml important_classes.py tsets_abc.py
about.md philosophy.md
next we will move a file there with mv
mv example.md docs/
what this does is change the path of the file from .../github-inclass-AymanBx/example.md
to .../github-inclass-AymanBx/docs/example.md
This doesn’t return anything, but we can see the effect with ls
$ ls
API.md helper_functions.py
CONTRIBUTING.md important_classes.py
LICENSE.md philosophy.md
README.md scratch.ipynb
_config.yml setup.py
_toc.yml tests_alt.py
about.md tests_helpers.py
abstract_base_class.py tests_imp.py
alternative_classes.py tsets_abc.py
docs/
We can also use ls
with a relative or absolute path of a directory to list tht location instead of our current working directory.
$ ls docs/
example.md
8.8.1. Moving multiple files with patterns#
let’s look at the list of files again.
$ ls
API.md helper_functions.py
CONTRIBUTING.md important_classes.py
LICENSE.md philosophy.md
README.md scratch.ipynb
_config.yml setup.py
_toc.yml tests_alt.py
about.md tests_helpers.py
abstract_base_class.py tests_imp.py
alternative_classes.py tsets_abc.py
docs/
What patterns are there in the file names that relate to what the file is for?
(use your readme or cat the files)
We can use the *
wildcard operator to move all files that match the pattern. We’ll start with the two yml
(yaml)
files that are both for the documentation.
mv *.yml docs/
Again, we confirm it worked by seeing that they are no longer in the working directory.
$ ls
API.md important_classes.py
CONTRIBUTING.md philosophy.md
LICENSE.md scratch.ipynb
README.md setup.py
about.md tests_alt.py
abstract_base_class.py tests_helpers.py
alternative_classes.py tests_imp.py
docs/ tsets_abc.py
helper_functions.py
and that they are in docs
$ ls docs/
_config.yml _toc.yml example.md
We see that most of the test files start with tests_
but one starts with
tsets_
. We can fix this!
We can use mv
to change the name as well. This is because “moving” a file and
is really about changing its path, not actually copying it from one location to
another and the file name is a part of the path.
$ mv tsets_abc.py tests_abc.py
$ ls
API.md important_classes.py
CONTRIBUTING.md philosophy.md
LICENSE.md scratch.ipynb
README.md setup.py
about.md test_abc.py
abstract_base_class.py tests_alt.py
alternative_classes.py tests_helpers.py
docs/ tests_imp.py
helper_functions.py
This changes the path from .../tsets_abc.py
to .../tests_abc.py
to. It is doing the same thing as when we use it to move a file from one folder to another folder, but changing a different part of the path.
Now we make a new folder:
$ mkdir tests
and move all of the test files there:
this is why good file naming is important even if you have not organized the whole project yet, you can use the good conventions to help yourself later.
$ mv test_* tests/
$ ls
API.md important_classes.py
CONTRIBUTING.md philosophy.md
LICENSE.md scratch.ipynb
README.md setup.py
about.md tests/
abstract_base_class.py tests_alt.py
alternative_classes.py tests_helpers.py
docs/ tests_imp.py
helper_functions.py
Nothing changed because my pattern doesn’t match any existing patterns.
I typed test_*
instead of tests_*
$ mv tests_* tests/
$ ls
API.md abstract_base_class.py philosophy.md
CONTRIBUTING.md alternative_classes.py scratch.ipynb
LICENSE.md docs/ setup.py
README.md helper_functions.py tests/
about.md important_classes.py
$ ls tests
test_abc.py tests_helpers.py
tests_alt.py tests_imp.py
8.10. Copying a file#
cp
copies
cp README.md docs/overview.md
Notice that we copied the contents of the file and put it in a newly named file called overview.md
all at once
$ ls docs
_config.yml _toc.yml example.md overview.md
$ cat docs/overview.md
# Practice
My name is Ayman
age = 27
8.11. Experience Report Evidence#
Save your history with:
history > activity-2025-02-20.md
then append your git status, and the contents of your github-in-class and github-in-class/docs with to help visually separat the parts.
echo "***--" >> activity-2025-02-20.md
git status >> activity-2025-02-20.md
echo "***--" >> activity-2025-02-20.md
ls >> activity-2025-02-20.md
echo "***--" >> activity-2025-02-20.md
ls docs/ >> activity-2025-02-20.md
then edit that file (on terminal, any text editor, or an IDE) to make sure it only includes things from this activity.
8.12. Prepare for next class#
Think through and make some notes about what you have learned about design so far. Try to answer the questions below in design_before.md. If you do not now know how to answer any of the questions, write in what questions you have.
- What past experiences with making decisions about design of software do you have?
- what experiences studying design do you have?
- What processes, decisions, and practices come to mind when you think about designing software?
- From your experiences as a user, how you would describe the design of command line tools vs other GUI based tools?
8.13. Badges#
badge steps marked lab are steps that you will be encouraged to use lab time to work on. In this case, in lab, we will check that you know what to do, but if we want you to do revisions those will be done through the badge.
Update your KWL chart with the new items and any learned items. And add a new row:
bash redirects
Clone the course website. Append the commands used and the contents of your
spring2025/.git/config
to a terminal_review.md (hint: history outputs recent commands and redirects can work with any command, not only echo). Edit the README.md, commit, and try to push the changes. Describe what the error means and which GitHub Collaboration Feature you think would enable you to push? (answer in theterminal_review.md
)
fork is the answer, must be one of the things higlighted in the link
badge steps marked lab are steps that you will be encouraged to use lab time to work on. For this one in particular, I am going to give you the messy repo in lab.
Update your KWL chart with any learned items. And add a new row:
bash redirects
(option) Get set up so that you can pull from the course website repo and push to your own fork of the class website by cloning the main repo, then forking it and adding your fork as an additional remote. Append the commands used and the contents of your
spring2025/.git/config
to a terminalpractice.md (hint:history
outputs recent commands and redirects can work with any command, not only echo). Based on what you know so far about forks and branches, what advantage does this setup provide? (answer in theterminal_practice.md
)(option) Get set up so that you can contribute to the course website repo from your local system. Note: you can pull from the
compsys-progtools/spring2025
repo, but you do not not have push permission, so there is more to do than clone. Append the commands used and the contents of yourspring2025/.git/config
to a git-remote-practice.md. Then, using a text editor (or IDE), wrap each log with three backticks to make them fenced code blocks and add headings to the sections.
clone (fork in browser)
git remote add
with any name and their fork
Organize a folder on your computer ( good candidate may be desktop or downloads folder), using only a terminal to make new directories, move files, check what’s inside them, etc. Answer reflection questions in a new file, terminal_organization_adv.md in your kwl repo. Tip: Start with a file explorer open, but then try to close it, and use only command line tools to explore and make your choices. If you get stuck, look up additional commands to do acomplish your goals.
# Terminal File moving reflection
1. How was this activity overall Did this get easier toward the end?
2. How was it different working on your own computer compared to the Codespace form?
3. Did you have to look up how to do anything we had not done in class?
4. When do you think that using the terminal will be better than using your GUI file explorer?
5. What questions/challenges/ reflections do you have after this?
6. Append all of the commands you used in lab below. (not from your local computer's history, from the codespace history)
8.14. Questions after class#
8.14.2. how am I suupose to remember most of these commands learned today in class#
We have a table of commands learned on the course website. But realistically, you’re not supposed to memorize them like the back of your hand. You’re supposed to practice using them and understand them better and that’s when you start remembering them better.