\midrule
1 & None & One file & Locks & RCS, SCSS\\
2 & Centralized & Multi-file & Merge before commit & CVS, SVN\\
- 3 & Distributed & Changeset & Commit before merge &
+ 3 & Distributed & Changeset & Commit before merge &
Git, Mercurial\\
\bottomrule
\end{tabular}
\frametitle{What is Git}
\begin{block}{Origins}
\begin{itemize}
- \item Pronounce: \textipa{[g\'\i t]}
+ \item Pronounce: \textipa{[g\'\i t]}
\item 2005 because \textit{Bitkeeper} changed terms
\item Linux kernel
\end{itemize}
- stupid. contemptible and despicable. simple. Take your pick from the
dictionary of slang.
- "global information tracker": you're in a good mood, and it actually
- works for you. Angels sing, and a light suddenly fills the room.
+ works for you. Angels sing, and a light suddenly fills the room.
- "goddamn idiotic truckload of sh*t": when it breaks
\end{minted}
\end{block}
\mint{console}{# emerge --ask dev-vcs/git}
Etc\ldots
\end{block}
-
+
\begin{block}{{\Large\Frowny\Smiley} Mac}
Install via XCode tools. Just run \mintinline{console}{|\$| git} and
when Git is not installed it will prompt you with instructions.
\end{block}
-
+
\begin{block}{{\Large\Frowny\Frowny} Windows}
Downoad the binary from \url{http://git-scm.com/download/win} and
install.
\end{minted}
\end{itemize}
\end{block}
-
+
\begin{block}{Windows}
\begin{itemize}
\item[Step 1.] Open \texttt{git-bash}. \texttt{git-bash} is a UNIX
\end{block}
\end{frame}
+\subsection{Repositories}
+\begin{frame}[fragile]
+ \frametitle{Create your first repository}
+ \begin{block}{Command}
+ \begin{minted}{console}
+|\$| cd projects
+|\$| git init myfirstproject
+Initialized empty Git repository in /home/frobnicator/projects/myfirstproject/.git/
+ \end{minted}
+ \end{block}
+
+ \begin{block}{Filesystem}
+ \begin{minted}{console}
+|\$| ls -a myfirstproject
+. .. .git
+|\$| ls myfirstproject/.git
+branches config description HEAD hooks info objects refs
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\subsection{Workflow}
+\begin{frame}
+ \frametitle{Four (five) stages}
+ \begin{itemize}
+ \item (Stash)
+ \item Workspace
+ \item Index
+ \item Local repo
+ \item Upstream repo
+ \end{itemize}
+\end{frame}
+
+\begin{frame}
+ \frametitle{Connect the stages}
+ \includegraphics[width=\linewidth]{workflow.png}
+\end{frame}
+
\section{Local}
+\begin{frame}
+ \frametitle{Everything is a commit}
+ \begin{block}{Forget what you have learned. These things are commits:}
+ \begin{itemize}
+ \item commit
+ \item tag
+ \item branch
+ \item \texttt{HEAD}
+ \end{itemize}
+ \end{block}
+ \begin{block}{Commits are structured in a tree}
+ \end{block}
+ \pause
+ \begin{block}{From now on: Tag along}
+ \end{block}
+\end{frame}
+
+\subsection{Add \& Commit}
+\begin{frame}[fragile]
+ \frametitle{Add (1)}
+ \begin{block}{Command}
+ \mintinline{bash}{git add [opts] [<pathspec>...]}
+ \end{block}
+ \begin{block}{Example: Shopping list}
+ \begin{minted}{console}
+|\$| git init shoppinglist
+Initialized empty Git repository in
+ /home/frobnicator/projects/shoppinglist/.git/
+|\$| cd shoppinglist/
+|\$| echo "milk" > shopping.txt
+|\$| echo "eggs" >> shopping.txt
+|\$| echo "ham" >> shopping.txt
+|\$| cat shopping.txt
+milk
+eggs
+ham
+ \end{minted}
+ \end{block}
+ \begin{block}{Where is the data?}
+ \pause
+ Workspace
+ \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Add (2)}
+ \begin{minted}{console}
+|\$| git status
+On branch master
+
+Initial commit
+
+Untracked files:
+ (use "git add <file>..." to include in what will be committed)
+
+ shopping.txt
+
+nothing added to commit but untracked files present (use "git add" to track)
+|\$| git add shopping.txt #git add .
+|\$| git status
+On branch master
+
+Initial commit
+
+Changes to be committed:
+ (use "git rm --cached <file>..." to unstage)
+
+ new file: shopping.txt
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Commit (1)}
+ \begin{minted}{console}
+|\$| export EDITOR=vim # nano, emacs, ed, ex, etc...
+|\$| git commit # Editor opens
+
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+# On branch master
+#
+# Initial commit
+#
+# Changes to be committed:
+# new file: shopping.txt
+#
+[master (root-commit) ae90376] Initial shopping list
+ 1 file changed, 3 insertions(+)
+ create mode 100644 shopping.txt
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Commit (2)}
+ \begin{block}{Results}
+ \begin{minted}{console}
+|\$| git status
+On branch master
+nothing to commit, working directory clean
+|\$| ls -a
+. .. .git shopping.txt
+ \end{minted}
+ \end{block}
+
+ \begin{block}{Where is the data}
+ \pause
+ Workspace + Local repository
+ \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Add \& Commit some more}
+ \begin{block}{We forgot the bread!}
+ \begin{minted}{console}
+|\$| echo "Bread" >> shopping.txt
+|\$| git add .
+|\$| git commit -m "We forgot the bread, oops"
+[master 8cb1d9b] We forgot the bread, oops
+ 1 file changed, 1 insertion(+)
+ \end{minted}
+ \end{block}
+
+ \begin{block}{Even quicker, let's add beer}
+ \begin{minted}{console}
+|\$| echo "Grolsch" >> shopping.txt
+|\$| git commit -am "Beer added"
+[master 99d65a3] Beer added
+ 1 file changed, 1 insertion(+)
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\subsection{Administration}
+\begin{frame}[fragile]
+ \frametitle{Log}
+ \begin{minted}{console}
+|\$| git log
+commit 99d65a34c02f5766ffa8e04b7c7121dfe41136ec
+Author: Frob Nicator <frob@nicat.or>
+Date: Tue Mar 15 19:15:05 2016 +0100
+
+ Beer added
+
+commit 8cb1d9bf8e4b45355b38600367a841fe9ceaae40
+Author: Frob Nicator <frob@nicat.or>
+Date: Tue Mar 15 19:13:55 2016 +0100
+
+ We forgot the bread, oops
+
+commit ae903769895cbb7c24b096e17049d20a8456953c
+Author: Frob Nicator <frob@nicat.or>
+Date: Tue Mar 15 19:04:40 2016 +0100
+
+ Initial shopping list
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Checkout (1)}
+ \begin{minted}{console}
+|\$| git log --oneline --decorate --graph --all
+* 99d65a3 (HEAD, master) Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 Initial shopping list
+|\$| cat shopping.txt
+milk
+eggs
+ham
+Bread
+Grolsch
+|\$| git checkout ae90376
+Note: checking out 'ae90376'.
+
+... # long error about detached head state
+
+HEAD is now at ae90376... Initial shopping list
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Checkout (2)}
+ \begin{minted}{console}
+|\$| git log --oneline --decorate --graph --all
+* 99d65a3 (master) Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 (HEAD) Initial shopping list
+|\$| cat shopping.txt # We got our old shopping list back!
+milk
+eggs
+ham
+|\$| git checkout master # or 99d65a3
+Previous HEAD position was ae90376... Initial shopping list
+Switched to branch 'master'
+|\$| git log --oneline --decorate --graph --all
+* 99d65a3 (HEAD, master) Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 Initial shopping list
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Differences (1)}
+ \begin{block}{Behaviour}
+ \begin{itemize}
+ \item\mintinline{console}{git diff HASH}\\
+ Compare index to said hash
+ \item\mintinline{console}{git diff HASH1 HASH2}\\
+ Compare the hashes
+ \end{itemize}
+ \end{block}
+
+ \begin{minted}{console}
+|\$| git diff ae90376
+diff --git a/shopping.txt b/shopping.txt
+index 1e19791..c41e7e5 100644
+--- a/shopping.txt
++++ b/shopping.txt
+@@ -1,3 +1,5 @@
+milk
+eggs
+ham
++Bread
++Grolsch
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Differences (2)}
+ \begin{minted}{console}
+|\$| git diff master
+|\$| vi shopping.txt # remove bread
+|\$| git diff master
+diff --git a/shopping.txt b/shopping.txt
+index c41e7e5..47c3623 100644
+--- a/shopping.txt
++++ b/shopping.txt
+@@ -1,5 +1,4 @@
+ milk
+ eggs
+ ham
+-Bread
+ Grolsch
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Oops we didn't want to remove the bread}
+ \begin{minted}[escapeinside=]{console}
+$ git stash
+Saved working directory and index state WIP on master: 99d65a3 Beer added
+HEAD is now at 99d65a3 Beer added
+$ git log --oneline --decorate --graph --all
+* 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
+|\
+| * 149d864 index on master: 99d65a3 Beer added
+|/
+* 99d65a3 (HEAD, master) Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 Initial shopping list
+ \end{minted}
+ \begin{block}{Stash}
+ This is material for an advanced git course.\\
+ Just remember you can checkout all hashes.
+ \end{block}
+\end{frame}
+
+\subsection{Branching}
+\begin{frame}[fragile]
+ \frametitle{Branching}
+ \begin{block}{Let's start from scratch}
+ \begin{minted}{console}
+|\$| git rm shopping.txt
+rm 'shopping.txt'
+|\$| echo -e "ham\nmilk\neggs" > list.txt
+|\$| git add .
+|\$| git status
+On branch master
+Changes to be committed:
+ (use "git reset HEAD <file>..." to unstage)
+
+ renamed: shopping.txt -> list.txt
+ \end{minted}
+ \end{block}
+ \pause
+ \begin{block}{Wait a minute, we removed that...}
+ \begin{minted}{console}
+|\$| git commit -m "Start from scratch"
+[master 33dff03] Start from scratch
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+ rename shopping.txt => list.txt (50%)
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Branching \& Merging (1) }
+ \begin{minted}[escapeinside=]{console}
+$ git checkout -b vega # or git branch vega; git checkout vega
+$ vi list.txt # change ham to tofu, add beans
+$ cat list.txt
+tofu
+milk
+eggs
+beans
+$ git commit -am "Added tofu and beans"
+[vega e74256e] Added tofu and beans
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+$ git log --oneline --decorate --graph --all
+* e74256e (HEAD, vega) Added tofu and beans
+* 33dff03 (master) Start from scratch
+| * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
+| |\
+|/ /
+| * 149d864 index on master: 99d65a3 Beer added
+|/
+* 99d65a3 Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 Initial shopping list
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Branching \& Merging (2) }
+ \begin{minted}[escapeinside=]{console}
+$ git checkout master
+$ cat list.txt
+ham
+milk
+eggs
+$ git log --oneline --decorate --graph --all
+* e74256e (vega) Added tofu and beans
+* 33dff03 (HEAD, master) Start from scratch
+| * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
+| |\
+|/ /
+| * 149d864 index on master: 99d65a3 Beer added
+|/
+* 99d65a3 Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 Initial shopping list
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Branching \& Merging (2) }
+ \begin{minted}[escapeinside=]{console}
+$ vi list.txt # change ham to cheese
+$ cat list.txt
+cheese
+milk
+eggs
+$ git commit -am "Change ham to cheese"
+[master a77f1e5] Change ham to cheese
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+$ git log --oneline --decorate --graph --all
+* a77f1e5 (HEAD, master) Change ham to cheese
+| * e74256e (vega) Added tofu and beans
+|/
+* 33dff03 Start from scratch
+| * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
+| |\
+|/ /
+| * 149d864 index on master: 99d65a3 Beer added
+|/
+* 99d65a3 Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 Initial shopping list
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Merging (1)}
+ \begin{block}{Noes, conflicts}
+ \begin{minted}{console}
+|\$| git merge vega
+Auto-merging list.txt
+CONFLICT (content): Merge conflict in list.txt
+Automatic merge failed; fix conflicts and then commit the result.
+ \end{minted}
+ \end{block}
+ \begin{block}{Contents of \texttt{list.txt}}
+ \begin{minted}{text}
+<<<<<<< HEAD
+cheese
+=======
+tofu
+>>>>>>> vega
+milk
+eggs
+beans
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Merging (2)}
+ \begin{block}{Resolving merge conflicts}
+ \begin{itemize}
+ \item Open all files listed
+ \item Remove all \texttt{<<<<< \ldots} and \texttt{>>>> \ldots}
+ \end{itemize}
+ \end{block}
+ \begin{block}{Contents of commit when you have done that}
+ \begin{minted}{console}
+Merge branch 'vega'
+
+Conflicts:
+ list.txt
+# ...
+
+# ...
+# On branch master
+# All conflicts fixed but you are still merging.
+#
+# Changes to be committed:
+# modified: list.txt
+#
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Merging (3)}
+ \begin{block}{And done!}
+ \begin{minted}[escapeinside=]{console}
+$ git commit -a
+[master 10a9e9e] Merge branch 'vega'
+$ git tree
+* 10a9e9e (HEAD, master) Merge branch 'vega'
+|\
+| * e74256e (vega) Added tofu and beans
+* | a77f1e5 Change ham to cheese
+|/
+* 33dff03 Start from scratch
+| * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
+| |\
+|/ /
+| * 149d864 index on master: 99d65a3 Beer added
+|/
+* 99d65a3 Beer added
+* 8cb1d9b We forgot the bread, oops
+* ae90376 Initial shopping list
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\subsection{Notes}
+\begin{frame}
+ \frametitle{Some notes}
+ \begin{itemize}
+ \item Make short commits, per feature
+ \item Try to only commit working code
+ \item No generatable stuff in the repo
+ \item Commit messages formatten:
+ \begin{itemize}
+ \item 72 Chars title
+ \item Enter, Enter
+ \item Body of the message in \emph{Imperative Present Tense}
+ \emph{change}, not \emph{changed} or \emph{changes}
+ \end{itemize}
+ \item Master contains only major releases
+ \item Develop contains development release
+ \item Feature branches
+ \end{itemize}
+\end{frame}
\section{Remote}
+\begin{frame}
+ \frametitle{Clone (1)}
+ \begin{itemize}
+ \item Github(you can get 5 free repos via student mail)
+ \item BitBucket
+ \item Gitlab(runs on science servers)
+ \item \mintinline{console}{git clone CLONEURL}
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Clone (2)}
+ \begin{block}{Clone}
+ \begin{minted}{console}
+|\$| git clone https://github.com/githubuser/reponame # With optional folder
+Cloning into 'reponame'...
+remote: Counting objects: 44, done.
+remote: Total 44 (delta 0), reused 0 (delta 0), pack-reused 44
+Unpacking objects: 100% (44/44), done.
+Checking connectivity... done.
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Push \& Pull}
+ \begin{block}{Pull}
+ Basically a merge of the remote branch with your \texttt{HEAD}. This
+ can lead to merge conflict. Only pull when you have committed
+ everything.
+ \begin{minted}{console}
+|\$| git pull origin BRANCHNAME
+ \end{minted}
+ \end{block}
+
+ \begin{block}{Push}
+ Push your changes to the remote. You have to pull first.
+ \begin{minted}{console}
+|\$| git push origin BRANCHNAME
+ \end{minted}
+ \end{block}
+\end{frame}
+
+\begin{frame}
+ \frametitle{Tags}
+ \begin{itemize}
+ \item \mintinline{console}{git tag TAGNAME}
+ \item Github interprets them as releases
+ \item Easy for releases
+ \item Literally a named commit
+ \item Push only tags:
+ \mintinline{console}{git push --tags origin master}
+ \end{itemize}
+\end{frame}
+
-\section{Conclusion}
+\section{Post scriptum}
+\subsection{Questions \& Conclusion}
+\begin{frame}
+ \frametitle{Questions}
+ \begin{center}{\Huge?}\end{center}
+ \pause
+ \begin{block}{If you want to be an expert}
+ Read: \emph{Git from the bottom up}~\footnote{\url{%
+ http://ftp.newartisans.com/pub/git.from.bottom.up.pdf}}
+ \end{block}
+\end{frame}
+
+\subsection{Aliasing}
+\begin{frame}[fragile]
+ \frametitle{Aliasing}
+ \begin{minted}{console}
+|\$| cat ~/.gitconfig
+[user]
+name = Frob Nicator
+email = frob@nicat.or
+
+[alias]
+tree = log --decorate --oneline --graph --all
+pushm = push origin master
+pushd = push origin develop
+|\$| git tree
+ \end{minted}
+\end{frame}
+
+\subsection{What is the difference betweeen all the clone urls?}
+\begin{frame}
+ \frametitle{SSH or HTTPS}
+ \begin{itemize}
+ \item SSH preferred over HTTPS due to security issues
+ \item SSH saves you from entering the password all the time
+ \item For a how-to about setting up SSH checkout the github tutorial
+ \item HTTPS easy for onetime checkout
+ \end{itemize}
+\end{frame}
+
+\subsection{Host your own git server}
+\begin{frame}[fragile]
+ \frametitle{Host your own git server}
+ \begin{block}{SSH (Easy)}
+ \begin{minted}{console}
+# adduser --shell /usr/bin/git-shell git}
+# su git -s /bin/bash
+|\$| mkdir .ssh
+|\$| chmod 700 .ssh
+|\$| touch .ssh/authorized_keys # Put public keys in here
+|\$| chmod 600 .ssh/*
+|\$| git init --bare newrepo.git
+ \end{minted}
+ \end{block}
+
+ \begin{block}{HTTP webinterface (Medium)}
+ GitList\footnote{\url{http://gitlist.org/}}
+ This presentation:
+ {\tiny\url{https://ygdrassil.martlubbers.net/git/ai-gitworkshop.git/}}
+ \end{block}
+
+ \begin{block}{HTTP+SSH (Hard)}
+ GitLab\footnote{\url{gitlab.com}}
+ \end{block}
+\end{frame}
\end{document}