Once you start writing your scripts, you'll soon find yourself handling files
named like script.sh
, script_bak.sh
, script_previous_previous.sh
,
script_last_working.sh
.. etc. There is one cure for them all: git
.
It was originally created by Linus Torvalds, the author of the Linux kernel,
for managing the source code of Linux, it slowly gained popularity in other
communities.
What git
does is managing versions of a directory tree. The managed subtree
is called a repository. Each saved version is called a commit. You
usually create a commit when the code you're working on behaves as expected 🙂.
By allowing you to go back to any committed version, git
effectively removes the
need for all _previous_working.sh
copies of your code.
Note
Please note the difference between git
and Google Docs - Google Docs keeps
track of all versions of a particular file. git
keeps track of manually
selected versions (snapshots) of a whole directory. That makes sense when
script1.sh
calls script2.sh
, and they have to match.
You will be using git
to hand in the final exam, so please take care to set
it up correctly. Once on every new machine you need to tell git who you are,
because the commits are 'signed' by the author.
git config --global user.email "ferda@mraveniste.cz"
git config --global user.name "Ferda Mravenec"
To be able to share your code, you need an account on a 'social coding' site like GitHub. If you don't have a GitHub account, please create one.
To upload your code, you need to add a key to GitHub here. This is how you generate the needed key:
# generate the private and public keys
ssh-keygen -t ed25519
# show the public key to copy and paste to github
cat ~/.ssh/id_ed25519.pub
And now after the tedious setup let's enjoy the benefits. You have to do the setup only once per machine, and then you use it for all your projects.
Let's store the current version of your scripts in unix-advanced
project.
Git repo is not a good place for data, we'll ignore the data directory.
# make sure we're in ~/projects/unix-advanced
pwd
# tell git we want to track this directory
git init
# tell git that we don't want to track and store the huge data
# (git is not good at storing big data)
echo 'data*' >> .gitignore
# check what git sees in our brand new repo
git status
# add a single file
git add workflow.sh
# make a commit
# add some descriptive message
git commit -m "solution to ngs-course exercises"
This is all you need to track your versions locally. If you want to share your creations with others, transfer it to another machine or just make a backup for yourself, you need to push it somewhere.
In your GitHub account, create a repository and use the suggested commands to add it as a remote to your local repo and push. Select Private if you don't want your code to be publicly accessible.
# use the commands suggested by GitHub to add a remote
git remote add origin git@github.com:{user}/{repo}.git
git push -u origin master
When using git, you can gradually learn about more concepts and commands, as you find the need for them. To give you a head start:
.. glossary:: working copy the directory you're currently working in ``git status`` check the working copy for changes versus last commit ``git diff`` show the changes in the working copy ``git add {file}`` add file to the next commit ``git commit`` create a commit from all added files (opens editor for commit message) ``git commit -am '{what i did}'`` shortcut for adding all changed files (previously in repo) and committing them ``git push`` upload the commits to a remote repository ``git pull`` download new commits from a remote repository, merge them into your working copy ``git stash`` can be used to "hide" local changes during ``pull`` ``git stash pop`` brings the "hidden" changes back ``git log`` show the previous commits ``git checkout -- {filename}`` overwrite the file with the version from the last commit
.. glossary:: ``git checkout -b {new-name}`` create a new branch from the current one and switch to it ``git push -u origin {branch-name}`` upload commits on current branch to a remote repository ``git checkout {branch-name}`` switch to another branch
.. glossary:: ``git pull`` if the remote branch has new commits and your local brach has some other commits ``pull`` will do a merge for you ``git checkout --theirs {file path}`` in conflict, choose the version from the remote branch ``git checkout --ours {file path}`` in conflict, choose the version from the local branch ``git merge --continue`` or ``git commit`` continue the merge after resolving conflicts (i'm used to ``git commit``, but the newer ``git merge --continue`` should be safer) ``git merge --abort`` abort the merge