diff --git a/README.md b/README.md index b8b5589..dd015e0 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The main document (the one you should run `pdflatex` on) is `larics-git-tutorial The classes are interactive, i.e., students are expected to follow along on their own laptops. -The material is appropriate for 2 classes of 2 hours (2x105 minutes). The first class should cover material up to the "Branches in git" slide. The second class should cover the material on working with branches. +The material is appropriate for 2 classes of 2 hours (2x90 minutes). The first class should cover the "Keeping track of your code" section, i.e., material up to slide 30 "Getting changes from the remote repository" The second class should cover the material on "Collaborating with others". The students should arrive to class prepared, i.e., they should: diff --git a/basicbasics.tex b/basicbasics.tex index b642f52..9ddbcec 100644 --- a/basicbasics.tex +++ b/basicbasics.tex @@ -1,4 +1,4 @@ -\section{The basic basics} +\section{Keeping track of your code} \begin{frame} @@ -41,7 +41,7 @@ \section{The basic basics} \end{itemize} \item Supports different workflows \begin{itemize} - \item We'll be using the GitHub workflow (more or less) + \item We'll be using the \href{https://guides.github.com/introduction/flow/}{GitHub flow} (more or less) \end{itemize} \end{itemize} @@ -90,10 +90,10 @@ \section{The basic basics} \begin{frame} -\frametitle{Basic terms: branch, master and head} +\frametitle{Basic terms: branch, main and head} -\begin{block}{Branch, master and head} -A \alert{branch} is simply a pointer to a commit. \alert{Master} is usually the name of the main branch (but does not have to be). \alert{HEAD} is a special pointer to the currently checked out commit. \\ +\begin{block}{Branch, main and head} +A \alert{branch} is simply a pointer to a commit. \alert{Main} is usually the name of the main branch (but does not have to be). \alert{HEAD} is a special pointer to the currently checked out commit. \\ \smallskip The commits with their parent-child relationships form a directed acyclic graph (DAG). \end{block} @@ -110,8 +110,7 @@ \section{The basic basics} \frametitle{Getting started on Github} -To begin working on a project using Github, you have to create a repository. There are two ways to do this: - +To begin working on a project using Github, you have to create a repository. There are three ways to do this: \begin{itemize} \item Create an empty repository @@ -124,6 +123,14 @@ \section{The basic basics} \begin{itemize} \item When you wish to improve and build upon another repository \item This creates your personal copy of the repository in which you can make your own commits + \item Common in open source projects with many contributors + \end{itemize} + + \medskip + \item \alert{Join an existing repository} + \begin{itemize} + \item The owner must add you to the repository + \item The most convenient collaboration mode for small and medium sized teams \end{itemize} \end{itemize} @@ -133,19 +140,18 @@ \section{The basic basics} \begin{frame}[fragile] -\frametitle{Making a Github fork and adding a collaborator} +\frametitle{Forking a repo and adding a collaborator} \begin{block}{Task A [Mirko]: Fork the example repository} - To fork a repository, simply click the \includegraphics[scale=0.35]{fork} \, icon in the top right corner of the repository webpage. For this tutorial, you will need to fork the \href{https://github.com/larics/git-tutorial-code.git}{larics/git-tutorial-code} repository. \end{block} \begin{block}{Task B [Mirko]: Add a collaborator to your forked repository} -In the GitHub user interface, on the \includegraphics[scale=0.35]{settings} \, tab of your forked repository, select the \texttt{Collaborators and teams} menu and add your partner as a collaborator with \texttt{Write} access. +In the GitHub user interface, on the \includegraphics[scale=0.35]{settings} \, tab of your forked repository, open the \texttt{Manage access} menu and add your partner as a collaborator with \texttt{Write} access. \end{block} \begin{block}{Task C [Slavko]: Accept the collaboration invitation} -Check your mail, or the list of notifications on Github. Accept the collaboration invitation. +Check your mail, or the list of notifications. Accept the collaboration invitation. \end{block} \end{frame} @@ -159,12 +165,13 @@ \section{The basic basics} \begin{block}{Cloning} Cloning creates a local copy of the repository, which includes all the commits in the repository -- the whole history. \begin{minted}{console} -> git clone git@github.com:/git-tutorial-code.git +> git clone git@github.com:/git-tutorial-code.git +> cd \end{minted} \end{block} \begin{block}{Task D [Mirko, Slavko]} -Clone Mirko's repository onto your computer. +Clone Mirko's repository onto your computer and \texttt{cd} into it. \end{block} \begin{itemize} @@ -175,6 +182,23 @@ \section{The basic basics} % ----------------------------------------------------------------------------- +\begin{frame} + +\frametitle{Visualizing your repository} + +\begin{itemize} + \item The \texttt{gitg} tool can visualize your repository + \item GitHub provides similar functionality with the Insights $\rightarrow$ Network menu. +\end{itemize} + +\begin{block}{Task E [Mirko, Slavko]} + Visualize your repository with \texttt{gitg} and on GitHub. +\end{block} + +\end{frame} + +% ----------------------------------------------------------------------------- + \begin{frame}[fragile] \frametitle{Repository structure} @@ -182,7 +206,7 @@ \section{The basic basics} What is contained in the repository directory? \begin{minted}{console} -> cd git-tutorial-code +> cd > ls -la > git status \end{minted} @@ -211,14 +235,50 @@ \section{The basic basics} \begin{frame}[fragile] - \frametitle{Your first commit} + \frametitle{Your first branch} - \begin{block}{Task E [Mirko, Slavko]} - Open \texttt{README.md} and add the following lines, then save the file: - \begin{minted}{text} -Maintainers: - + \begin{block}{Task F [Mirko, Slavko]} + Create a branch, off of the \texttt{main} branch: + + \begin{minted}{console} +> git checkout -b -git-tutorial +> git status +> git branch -v +> gitg& \end{minted} + + \end{block} + +\end{frame} + +% ----------------------------------------------------------------------------- + + +\begin{frame}[fragile] + +\frametitle{Branching - recap} + +\begin{itemize} +\item A \texttt{branch} is simply a "pointer" to a commit +\item \texttt{git checkout } updates the files in the working tree to match the specified branch +\item \texttt{git checkout -b } creates a new branch at the current commit +\item You can use \texttt{gitg} to visualize your branches +\item Use descriptive branch names, separate words with dashes +\item Prefix "private" branches with your name +\item Branch early and often (but do not push every branch, and clean up regularly!) +\end{itemize} + +\end{frame} + + +% ----------------------------------------------------------------------------- + + +\begin{frame}[fragile] + \frametitle{Your first commit} + + \begin{block}{Task G [Mirko, Slavko]} + Open \texttt{README.md} and change the maintainer name (make yourself the maintainer), then save the file: Run the following, and observe what is happening. @@ -227,8 +287,8 @@ \section{The basic basics} > git diff > git add README.md > git status -> git gui -> git commit -m "Add maintainer." +> git gui& +> git commit -m "Change the maintainer" > git status > git log \end{minted} @@ -271,11 +331,35 @@ \section{The basic basics} % ----------------------------------------------------------------------------- +\begin{frame}[fragile] + \frametitle{Discarding unstaged changes} + + \begin{block}{Task I [Mirko, Slavko]} + \begin{itemize} + \item Delete a big chunk of text from \texttt{README.md}. Do not add or commit. + + \item To find out what is going on, use \texttt{git status} and \texttt{git diff}. + \medskip + \item Discard the changes by retrieving ("checking out") the last commited version of the file (can also be a directory) using the \texttt{checkout} command: + + \begin{minted}{console} +> git checkout README.md + \end{minted} + + Note that the checked out version will contain the staged changes, i.e., \texttt{checkout} affect only the workspace, not the index. + \end{itemize} + \end{block} +\end{frame} + +% ----------------------------------------------------------------------------- + \begin{frame} \frametitle{Managing staged changes} - + \begin{block}{Task H [Mirko, Slavko]} + Make some more changes to some file(s) in your working tree. + \end{block} \begin{itemize} \item To get a list of staged and unstaged files, run \texttt{git status}. @@ -286,10 +370,7 @@ \section{The basic basics} \item To view the \textbf{staged} changes in the \textit{diff} format, you can also use \texttt{git gui}, or you can run \texttt{git diff --cached} \item You can finely tune what goes into the commit by staging/unstaging individual lines using \texttt{git gui}. - \begin{itemize} - \item The shortcut for (un)staging all changes in a file is Ctrl-U - \item For those who prefer the command line, you can use the \texttt{-p} switch of \texttt{git add} and \texttt{git reset}. - \end{itemize} + (The shortcut for (un)staging all changes in a file is Ctrl-U) \end{itemize} \end{frame} @@ -300,7 +381,7 @@ \section{The basic basics} \frametitle{Making some more commits} -\begin{block}{Task F [Mirko, Slavko]: Adding a license and \texttt{.gitignore}} +\begin{block}{Task J [Mirko, Slavko]: Adding a license and \texttt{.gitignore}} \begin{itemize} \item Add a license to the project. Create a \texttt{LICENSE.txt} file and copy the \href{https://www.apache.org/licenses/LICENSE-2.0.txt}{Apache License 2.0 text} into this file. \item Create a \texttt{.gitignore} file, with the following two lines: @@ -312,10 +393,11 @@ \section{The basic basics} \end{itemize} \end{block} -\begin{block}{Task G [Mirko]} - Open \texttt{README.md}. Under the package description (the second line), add and commit something to annoy your colleague (but keep it friendly :)). For example: +\begin{block}{Task K [Slavko]} + Open \texttt{README.md}. Under the package description (the second line), add and commit something to annoy your colleague, for example: \begin{minted}{text} -Developed without any help from that guy Slavko! +Mirko is churning out more spaghetti code +than a trattoria in Napoli. \end{minted} \end{block} @@ -323,55 +405,35 @@ \section{The basic basics} % ----------------------------------------------------------------------------- -\begin{frame}[fragile] - \frametitle{Discarding unstaged changes} - - \begin{block}{Task H [Mirko, Slavko]} - \begin{itemize} - \item Delete a big chunk of text from \texttt{README.md}. Do not add or commit. - - \item To find out what is going on, use \texttt{git status}. - \medskip - \item Discard the changes by retrieving ("checking out") the last commited version of the file (can also be a directory) using the \texttt{checkout} command: - - \begin{minted}{console} -> git checkout README.md - \end{minted} - - Note that the checked out version will contain the staged changes. - \end{itemize} - \end{block} -\end{frame} -% ----------------------------------------------------------------------------- -\begin{frame}[fragile] - -\frametitle{Discarding many unwanted changes} - - \begin{itemize} - \item If you have made many changes in your working tree, spanning several files, you can discard all of them at once (this also includes the staged changes): - \begin{minted}{console} -> git reset --hard - \end{minted} - - \item This will restore all tracked files in the working tree to the most recently committed version (i.e. the \texttt{HEAD} commit). - \end{itemize} - -\begin{block}{Task I [Mirko, Slavko]: Discarding several unwanted changes} - \begin{itemize} - \item Delete several files from the cloned example repository. Do not commit the changes. - \item Check the output of \texttt{git status}. - \item Discard all changes as shown above. - \end{itemize} -\end{block} - -\end{frame} +%\begin{frame}[fragile] +% +%\frametitle{Discarding many unwanted changes} +% +% \begin{itemize} +% \item If you have made many changes in your working tree, spanning several files, you can discard all of them at once (this also includes the staged changes): +% \begin{minted}{console} +%> git reset --hard +% \end{minted} +% +% \item This will restore all tracked files in the working tree to the most recently committed version (i.e. the \texttt{HEAD} commit). +% \end{itemize} +% +%\begin{block}{Task I [Mirko, Slavko]: Discarding several unwanted changes} +% \begin{itemize} +% \item Delete several files from the cloned example repository. Do not commit the changes. +% \item Check the output of \texttt{git status}. +% \item Discard all changes as shown above. +% \end{itemize} +%\end{block} +% +%\end{frame} % ----------------------------------------------------------------------------- \begin{frame} -\frametitle{Going back in time} +\frametitle{Going back in time 1/3} \begin{itemize} \item A big point in using a version control system such as git is the ability to retrieve older versions of files in the project. @@ -384,227 +446,75 @@ \section{The basic basics} \begin{frame}[fragile] -\frametitle{Going back in time - 2} +\frametitle{Going back in time 2/3} - \begin{block}{Task J [Mirko, Slavko]} - \begin{itemize} - \item Delete a big chunk of text from \texttt{LICENSE.txt}. - \item Commit your destruction of the license file. - \item Git allows you to retrieve a version of a file from an earlier commit. To identify the desired commit, you can: +\begin{block}{Task L: Checking out an earlier commit [Mirko, Slavko]} + \begin{itemize} + \item Identify an interesting commit in your history by either: \begin{itemize} - \item use the \texttt{gitg} tool - \item run \texttt{git log} (add \texttt{--oneline} for an abbreviated list of commits). + \item running \texttt{git log} (add \texttt{--oneline} for an abbreviated list of commits), + \item using the \texttt{gitg} tool. \end{itemize} - \item Perform the retrieval by running: + \item Check out that commit into your working tree \begin{minted}{console} -> git checkout +> git checkout \end{minted} - Git will place the checked out version of the file in the working tree, and will also stage the changes for you. - \item Don't forget to specify the file, as \texttt{checkout} with a commit ID, but without a file, means something else! - \end{itemize} - - \end{block} -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - \frametitle{Pushing the changes to the remote repository} - - \begin{itemize} - \item \texttt{commit} only saves changes \alert{locally}! - \item The command \texttt{git push} is used to upload the commits you have made to a branch in a remote repository (also known as just \textit{remote}). In this case, the \texttt{master} branch on the \texttt{origin} remote: - + \item This will bring you in a so-called \emph{detached head} state (sounds more dangerous than it acually is :) + \item This is useful in situations where you want to build a previous version of your code that you know is working + \item Bring \texttt{HEAD} back to the tip of your tutorial branch \begin{minted}{console} -> git push origin master +> git checkout -git-tutorial \end{minted} - \begin{itemize} - \item Note that you can simply call \texttt{git push} if you have set up your local branch to be a tracking branch. - \item This will be explained later; in most cases, git will have already automatically configured this for you. \end{itemize} - \end{itemize} - - \begin{block}{Task K [Mirko, Slavko]} - Try pushing the commits you have made to Mirko's repository. - \end{block} +\end{block} - \end{frame} % ----------------------------------------------------------------------------- - \begin{frame}[fragile] - \frametitle{Dealing with conflicts} - - \begin{block}{Collaboration issues} -What happens when somebody else pushed changes to the remote repository before us? In this case, git refuses to push. We must synchronize our local repository first! - \end{block} - - Synchronizing the remote changes is a two-step process: - \begin{enumerate} - \item \texttt{fetch} the changes from the remote repository - \item \texttt{merge} the changes into your local branch - \end{enumerate} - - \begin{minted}{console} -> git fetch -> git status -> git diff master origin/master -> git merge origin/master - \end{minted} - - \begin{block}{Understanding \texttt{diff}} - \texttt{git diff a b} shows changes that need to be applied to \texttt{a} to make it the same as \texttt{b}. \texttt{a} and \texttt{b} are references to any two commits. - \end{block} - -\end{frame} +\frametitle{Going back in time 3/3} -% ----------------------------------------------------------------------------- +Sometimes, you want to retrieve a previously committed version of a specific file. -\begin{frame}[fragile] - \frametitle{Dealing with conflicts: merging} - \begin{itemize} - \item When you call \texttt{merge}, git adds a special commit known as a \textit{merge commit} to your local branch - \item The merge commit has two parent commits: your local previous head commit, and the other side's commit (in this case, the \textit{other side} is the same branch in the remote repository). - \end{itemize} - \begin{block}{\texttt{fetch}+\texttt{merge}=\texttt{pull}?} + \begin{block}{Task M [Mirko, Slavko]} \begin{itemize} - \small - \item \texttt{pull} will do \texttt{fetch} and \texttt{merge} in a single step - \item If the remote version has changed, and you have made local commits before pulling the remote changes, you might get yourself into trouble.\footnote{A really nice article advocating the use of \texttt{fetch}+\texttt{merge} can be found on \href{http://longair.net/blog/2009/04/16/git-fetch-and-merge/}{Mark's Blog}} - \item When you are getting back to work on a branch that you share with someone else, pull the remote changes before making your own commits! This helps avoid unnecesary merge commits by fast-forwarding. - \end{itemize} - \end{block} -\end{frame} - -% ----------------------------------------------------------------------------- -\begin{frame}[fragile] - \frametitle{Resolving conflicts} - - After merging, the file ends up in a conflicted state: - \begin{minted}{console} -> git merge origin/master -> git status -> git gui - \end{minted} - - Conflict markers inside the file: - \begin{minted}{diff} -<<<<<<< HEAD -Code from the checked out branch ("local" in git gui) -======= -Code from the other branch ("remote" in git gui) ->>>>>>> origin/master - \end{minted} - - To resolve the conflict, manually edit the file, mark resolution with \texttt{git add}, commit and push: + \item Identify a specific file version in your commit history. + \item Perform the retrieval by running: \begin{minted}{console} -> git add -> git commit -> git push origin master +> git checkout \end{minted} + \item Git will place the checked out version of the file in the \emph{staging area}. + \item How do you make further tweaks to the checked out version? + \item How do you discard this version? + \end{itemize} -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - \frametitle{Dealing with conflicts: merging} - - - \begin{block}{Task L [\textless the loser\textgreater]} - \begin{itemize} - \item Synchronize the remote changes. - \item Resolve the conflict (if any). - \item Push your changes. - \end{itemize} - \end{block} - - \begin{block}{Task M [\textless the winner\textgreater]} - \begin{itemize} - - \item Synchronize the new remote changes that \textless the loser\textgreater has now managed to push. - - \end{itemize} \end{block} - - \end{frame} - % ----------------------------------------------------------------------------- - - \begin{frame}[fragile] - -\frametitle{Reverting previous commits} - + \frametitle{Pushing the changes to the remote repository} + \begin{itemize} - \item Another benefit of splitting the work in different commits is the ability to undo them using \texttt{git revert}. - \item To revert the offending commit: + \item \texttt{commit} only saves changes \alert{locally}! + \item The command \texttt{git push} is used to upload the commits you have made to a branch in a remote repository (also known as just \textit{remote}). + \item When you are pushing a local branch for the first time, tell git that to track the remote branch with your local branch: \begin{minted}{console} -> git revert +> git push -u origin + \end{minted} + \item On subsequent pushes you can simply call + \begin{minted}{console} +> git push \end{minted} - \item Reverting generates a \textit{revert commit}, which has the exactly opposite (inverse) set of changes. - \end{itemize} - - \begin{block}{Task N [Slavko]: Slavko gets his revenge} - \begin{itemize} - \item Revert Mirko's annoying commit. - - \end{itemize} - \end{block} - -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - -\frametitle{Amending the last commit} - -In the special case when you want to add aditional changes to the \textit{last commit} that you have made, \textbf{and if you have not yet pushed that commit}: - - \begin{enumerate} - \item Stage the additional changes using \texttt{git add} - \item Inspect the changes, as previously described - \item Run \texttt{git commit --amend} - \begin{itemize} - \item In case you only wish to amend the commit description, just run \texttt{git commit --amend}, without staging any changes. \end{itemize} - \end{enumerate} - - \begin{block}{Task O [Slavko]} - Amend the description of the revert commit that you have just made: \texttt{Revert Mirko's rudeness}. Push the revert commit. - -\end{block} - \begin{block}{Task P [Mirko]} - Pull Slavko's changes. + \begin{block}{Task N [Mirko, Slavko]} + Push the commits you have made to Mirko's repository. \end{block} - -\end{frame} - -% ----------------------------------------------------------------------------- - - -\begin{frame} - -\frametitle{Visualizing your repository} - -\begin{itemize} - \item The \texttt{gitg} tool can visualize your repository - \item GitHub provides similar functionality with the Graphs $\rightarrow$ Network menu. -\end{itemize} - -\begin{block}{Task Q [Mirko, Slavko]} - Visualize your repository with \texttt{gitg} and on GitHub. Notice how the history is not linear. -\end{block} - \end{frame} % ----------------------------------------------------------------------------- @@ -641,4 +551,35 @@ \section{The basic basics} \end{itemize} \end{itemize} \end{block} -\end{frame} \ No newline at end of file +\end{frame} + +% ----------------------------------------------------------------------------- + +%\begin{frame}[fragile] +% +%\frametitle{Amending the last commit} +% +%In the special case when you want to add aditional changes to the \textit{last commit} that you have made, \textbf{and if you have not yet pushed that commit}: +% +% \begin{enumerate} +% \item Stage the additional changes using \texttt{git add} +% \item Inspect the changes, as previously described +% \item Run \texttt{git commit --amend} +% \begin{itemize} +% \item In case you only wish to amend the commit description, just run \texttt{git commit --amend}, without staging any changes. +% \end{itemize} +% \end{enumerate} +% +% \begin{block}{Task O [Slavko]} +% Amend the description of the revert commit that you have just made: \texttt{Revert Mirko's rudeness}. Push the revert commit. +% +%\end{block} +% +% \begin{block}{Task P [Mirko]} +% Pull Slavko's changes. +% \end{block} +% +% +%\end{frame} + +% ----------------------------------------------------------------------------- \ No newline at end of file diff --git a/branches.tex b/branches.tex deleted file mode 100644 index 95473fe..0000000 --- a/branches.tex +++ /dev/null @@ -1,240 +0,0 @@ -\section{Working with branches} - -\begin{frame} - -\frametitle{Branches in git} - -\begin{itemize} - \item Branches are used for isolated experimenting (short-lived branches), and isolated feature development (long-lived branches) - \item Branching often is encouraged - \item Git is specifically designed for efficient work with branches - \item A branch is \textbf{simply a pointer to a commit} - \item The default branch name is \alert{master} -\end{itemize} - -\begin{block}{When do I need a branch?} - \begin{itemize} - \item When you are beginning to work on a new feature - \item When you want to make experimental commits - \item When you want to single out a change (can be several commits) for making a pull request - \item Whenever you feel like it! - \end{itemize} -\end{block} - -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - -\frametitle{Creating a branch} - -Creating a branch: -\begin{minted}{console} -> git branch -\end{minted} - -Switching to a branch: -\begin{minted}{console} -> git checkout -\end{minted} - -Or, in one command: -\begin{minted}{console} -> git checkout -b -\end{minted} - -Listing local branches: -\begin{minted}{console} -> git branch -v -\end{minted} - -\begin{block}{Two uses of checkout} - \begin{itemize} - \item Notice that we have already used \texttt{checkout} for checking out an earlier version of a file. This does not the affect the head commit in any way. - \item The \texttt{checkout} command is also used for switching to another branch, which of course changes the head commit (and the files in the working tree)! - \end{itemize} -\end{block} - -% TODO: add figures! - -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - -\frametitle{Working on a branch} - -\begin{block}{Naming branches} - Branches are usually named with dashes, e.g. \texttt{"pose-update-optimization"}, and can be prefixed with a name if the repository is a shared and one person is working on them (e.g. \texttt{"matt-new-renderer"}). -\end{block} - -\begin{block}{Task R [Mirko]: Bugfix on a new branch} -There is a bug in the \texttt{fact} function of the demo shell program. - \begin{itemize} - \item Create and checkout a new appropriately named branch. - \item Fix the bug - \begin{itemize} - \item C++: also change \texttt{short} to \texttt{long long} in a separate commit - \end{itemize} - \item Commit. - \end{itemize} -\end{block} - -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - -\frametitle{Merging branches locally} - -After you are finished working on the bugfix, it's time to merge it back into the master branch. -\begin{minted}{console} -> git checkout master -> git merge -\end{minted} - -After you have merged the branch, perform cleanup by deleting it:\begin{minted}{console} -> git branch -d -\end{minted} - -To delete an unmerged branch, you have to use the \texttt{-D} option. - -\medskip -Merge conflicts are handled in the same way as discussed before. Remote branches at origin are also just special kinds of branches, so we have been working with branches all along :) - -\end{frame} -% ----------------------------------------------------------------------------- - - -\begin{frame}[fragile] - -\begin{multicols}{2} - \begin{figure} - \includegraphics[scale=0.5]{3-way-merge-before} - \end{figure} - \begin{figure} - \includegraphics[scale=0.5]{3-way-merge-after} - \end{figure} -\end{multicols} - - \begin{block}{Task S [Mirko]: Merge the bugfix} - Merge your bug fix to the \texttt{master} branch and then push the \texttt{master} branch. Have your colleague pull the changes before they continue working. - \end{block} -\end{frame} -% ----------------------------------------------------------------------------- - - -\begin{frame}[fragile] - -\frametitle{Pushing a new branch to a remote} - - \begin{itemize} - \item As with commits, newly created branches and the commits in them are (so far) stored only in the local repository - \item Uploading them to the remote repository is performed by pushing. - \item Newly created branches have to be pushed with the following command: -\begin{minted}{console} -> git push -u -\end{minted} - This sets up the local branch as a \textit{tracking branch} of the remote branch. - \begin{itemize} - \item \texttt{git status} will now show you how many new commits ahead the branches are one related to another - \item \texttt{git push} will work without having to specify the remote - \item When you \texttt{clone} a repository, this is automatically set up for you for the \texttt{master} branch, and for any existing branches that you check out - \end{itemize} - \end{itemize} -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - -\frametitle{Pushing a new branch to a remote} - -\begin{block}{Deleting remote branches} - \begin{itemize} - \item Can be done from the Github interface; - \\ run \texttt{git fetch --prune} afterwards to clean them up in your local copy of the remote repository - \item To delete a remote branch using the command-line interface, run \texttt{git push --delete } - \end{itemize} -\end{block} - -\begin{block}{Task T [Slavko]: New feature on a remote branch} - \begin{itemize} - \item Create a new branch in which you will implement the feature - \item Implement a \texttt{square} command for the demo shell program, which computes the square of the provided argument - \item After making the commits which implement the feature, push the feature branch to the \texttt{origin} remote. - \end{itemize} -\end{block} -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - -\frametitle{Pull requests} - -\begin{block}{Task [Slavko]: Pull request} - \begin{itemize} - \item Look for your branch in the web interface of the GitHub repository and create a pull request for the master branch of your repository. - \item Have Mirko review the pull request. - \item If they find issues, correct them by pushing additional commits in the branch. The pull request will be automatically updated. - \item Delete the branch after it has been merged. - \end{itemize} - -\end{block} - -\begin{block}{Code review} - -Pull requests are an efficient and transparent code review mechanism. Code review is good. Pull requests are good. Use pull requests :) -\end{block} - -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame}[fragile] - -\frametitle{Working with multiple remotes} - -\begin{block}{Why would I need multiple remotes?} - \begin{itemize} - \item We can get code changes from any repository, not just our remote repository (which is automatically set up as a remote named \texttt{origin} when cloning) - \item A typical example is getting changes from the \textit{upstream} repository, i.e., the repository that we forked. - \end{itemize} -\end{block} - -Listing and adding remotes: -\begin{minted}{console} -> git remote add git@: -> git remote -v -\end{minted} - -We can now work with the new remote in the same way as with \texttt{origin} (except we can't push into it!), e.g.: -\begin{minted}{console} -> git fetch -> git merge / -\end{minted} - -\end{frame} - -% ----------------------------------------------------------------------------- - -\begin{frame} - -\frametitle{Merging upstream changes} - -\begin{block}{Task: Merge upstream changes} - \begin{itemize} - \item Set up a remote called \texttt{upstream} pointing to \href{https://github.com/larics/git-tutorial-code.git}{the original repository you forked} - \item \texttt{fetch} the \texttt{upstream} repository and compare its \texttt{master} branch with your \texttt{master} branch. - \item Optional: for experimenting how the upstream changes will play with your changes, create a new branch. - \item Merge the upstream \texttt{master} branch into your \texttt{master} branch (or first into your experimental branch, and then merge your experimental branch into your \texttt{master}). - \end{itemize} -\end{block} - -\end{frame} - -% ----------------------------------------------------------------------------- diff --git a/collaboration.tex b/collaboration.tex new file mode 100644 index 0000000..d7868f4 --- /dev/null +++ b/collaboration.tex @@ -0,0 +1,274 @@ +\section{Collaborating with others} + +% ----------------------------------------------------------------------------- + + +\begin{frame}[fragile] + \frametitle{Getting changes from the remote repository} + + Getting remote changes is a two-step process: + \begin{enumerate} + \item \texttt{fetch} the changes from the remote repository + \begin{minted}{console} +> git fetch +> git status +> git diff origin/ + \end{minted} + \item \texttt{merge} the changes into your local branch + \begin{minted}{console} +> git merge origin/ + \end{minted} + \end{enumerate} + + \begin{block}{Understanding \texttt{diff}} + \texttt{git diff a b} shows changes that need to be applied to \texttt{a} to make it the same as \texttt{b}. \texttt{a} and \texttt{b} are references to any two commits. + \end{block} + +\end{frame} + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + \frametitle{Syncing your code: merging} + \begin{itemize} + \item When you call \texttt{merge}, git adds a special commit known as a \textit{merge commit} to your local branch + \item The merge commit has two parent commits: your local previous head commit, and the other side's commit. + \end{itemize} + \begin{block}{\texttt{fetch}+\texttt{merge}=\texttt{pull}?} + \begin{itemize} + \small + \item \texttt{pull} will do \texttt{fetch} and \texttt{merge} in a single step + \item If the remote version has changed, and you have made local commits before pulling the remote changes, you might get yourself into trouble.\footnote{A really nice article advocating the use of \texttt{fetch}+\texttt{merge} can be found on \href{http://longair.net/blog/2009/04/16/git-fetch-and-merge/}{Mark's Blog}} + \item When you are getting back to work on a branch that you share with someone else, always \texttt{fetch}first to avoid unpleasant surprises. + \end{itemize} + \end{block} +\end{frame} + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + \frametitle{Merge conflicts} + + \begin{block}{Task O [Slavko]} + \begin{itemize} + \item Merge the remote changes + \item Resolve the conflicts (if any) + \item Push your changes + \item (After Mirko completes his task) Fetch the new \texttt{master} + \end{itemize} + \end{block} + + \begin{block}{Task P [Mirko]} + \begin{itemize} + + \item Fetch Slavko's changes + \item Merge Slavko's changes into your branch + \item Use \texttt{gitg} to examine what happened + \end{itemize} + \end{block} + +\end{frame} + +% ----------------------------------------------------------------------------- +\begin{frame}[fragile] + \frametitle{Resolving merge conflicts} + + After merging, some files might end up in a conflicted state: + \begin{minted}{console} +> git merge origin/ +> git status +> git gui + \end{minted} + + Conflict markers inside the file: + \begin{minted}{diff} +<<<<<<< HEAD +Code from the checked out branch ("local" in git gui) +======= +Code from the other branch ("remote" in git gui) +>>>>>>> origin/ + \end{minted} + + To resolve the conflict, manually edit the file, mark resolution with \texttt{git add}, commit and push: + \begin{minted}{console} +> git add +> git commit -m "" +> git push origin + \end{minted} + +\end{frame} + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + +\frametitle{Visualizing merges} + +\begin{multicols}{2} + \begin{figure} + \includegraphics[scale=0.5]{3-way-merge-before} + \end{figure} + \begin{figure} + \includegraphics[scale=0.5]{3-way-merge-after} + \end{figure} +\end{multicols} + +\end{frame} + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + +\frametitle{Reverting previous commits} + + \begin{itemize} + \item Another benefit of splitting the work in different commits is the ability to undo them using \texttt{git revert}. + \item To revert the offending commit: + \begin{minted}{console} +> git revert + \end{minted} + \item Reverting generates a \textit{revert commit}, which has the exactly opposite (inverse) set of changes. + \end{itemize} + + \begin{block}{Task Q [Mirko]: Mirko gets his revenge} + \begin{itemize} + \item Revert Slavko's annoying commit. + \item Use \texttt{gitg} to examine what happened + \item Merge your branch into the \texttt{master} branch + \item Push your \texttt{master} branch to \texttt{origin} + \end{itemize} + \end{block} +\end{frame} + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + +\frametitle{Cleaning up local branches} + +Branches are a powerful and useful tool. However, to be used effectively, we must maintain them regularly. Generally, there are two types of branches +\begin{itemize} + \item Short-lived branches (for bugfixes and features) + \item Long-lived branches +\end{itemize} + +After merging a short-lived branch, perform cleanup by deleting it: +\begin{minted}{console} +> git branch -d +\end{minted} + +To delete an unmerged branch, you have to use the \texttt{-D} option, but be careful with this option, as the commits it was pointing to will become difficult to reach. + +\end{frame} + + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + +\frametitle{Cleaning up remote branches} + +\begin{block}{Deleting remote branches} + \begin{itemize} + \item Can be done from the Github interface; + \\ run \texttt{git fetch --prune} afterwards to clean them up in your local copy of the remote repository + \item To delete a remote branch using the command-line interface, run \texttt{git push --delete } + \end{itemize} +\end{block} + +\begin{block}{Task R [Mirko, Slavko]: Clean up your branches} + Delete both the local and remote branches. +\end{block} +\end{frame} + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + +\frametitle{Issues and pull (merge) requests 1/2} + +\emph{Pull requests} are an efficient and transparent code review mechanism. GitLab calls them \emph{Merge requests}. + +\begin{block}{Task S [Mirko]: Create an Issue} +Examine the demo application and create an issue through the GitHub Web UI. +\end{block} + +\begin{block}{Task T [Slavko]: Merge request} +Implement the requested fix in a new branch. Commit, and do not forget to \emph{reference the issue} in the commit message. Create a Merge request. +\end{block} + +\begin{block}{Task U [Mirko, Slavko]: Code review} +Perform code review, merge the MR and delete the branch. +\end{block} + + +\end{frame} + +% ----------------------------------------------------------------------------- + +\begin{frame}[fragile] + +\frametitle{Issues and pull (merge) requests 2/2} + +\emph{Pull requests} are an efficient and transparent code review mechanism. GitLab calls them \emph{Merge requests}. + +\begin{block}{Task V [Slavko]: Create an Issue} +Ask for a \texttt{square} command to be implemented for the demo shell program. +\end{block} + +\begin{block}{Task W [Mirko]: Merge request} +Implement the requested feature in a new branch. Commit, and do not forget to \emph{reference the issue} in the commit message. Create a Merge request. +\end{block} + +\begin{block}{Task X [Mirko, Slavko]: Code review} +Perform code review, merge the MR and delete the branch. +\end{block} + + +\end{frame} + +% ----------------------------------------------------------------------------- + +%\begin{frame}[fragile] +% +%\frametitle{Working with multiple remotes} +% +%\begin{block}{Why would I need multiple remotes?} +% \begin{itemize} +% \item We can get code changes from any repository, not just our remote repository (which is automatically set up as a remote named \texttt{origin} when cloning) +% \item A typical example is getting changes from the \textit{upstream} repository, i.e., the repository that we forked. +% \end{itemize} +%\end{block} +% +%Listing and adding remotes: +%\begin{minted}{console} +%> git remote add git@: +%> git remote -v +%\end{minted} +% +%We can now work with the new remote in the same way as with \texttt{origin} (except we can't push into it!), e.g.: +%\begin{minted}{console} +%> git fetch +%> git merge / +%\end{minted} +% +%\end{frame} + +% ----------------------------------------------------------------------------- + +%\begin{frame} +% +%\frametitle{Merging upstream changes} +% +%\begin{block}{Task: Merge upstream changes} +% \begin{itemize} +% \item Set up a remote called \texttt{upstream} pointing to \href{https://github.com/larics/git-tutorial-code.git}{the original repository you forked} +% \item \texttt{fetch} the \texttt{upstream} repository and compare its \texttt{master} branch with your \texttt{master} branch. +% \item Optional: for experimenting how the upstream changes will play with your changes, create a new branch. +% \item Merge the upstream \texttt{master} branch into your \texttt{master} branch (or first into your experimental branch, and then merge your experimental branch into your \texttt{master}). +% \end{itemize} +%\end{block} +% +%\end{frame} + +% ----------------------------------------------------------------------------- diff --git a/figures/FER_logo.png b/figures/FER_logo.png new file mode 100644 index 0000000..ca6eb96 Binary files /dev/null and b/figures/FER_logo.png differ diff --git a/figures/fer_logo.jpg b/figures/fer_logo.jpg deleted file mode 100644 index 9246290..0000000 Binary files a/figures/fer_logo.jpg and /dev/null differ diff --git a/larics-git-tutorial-intro.tex b/larics-git-tutorial-intro.tex index fa9502f..7c561d9 100644 --- a/larics-git-tutorial-intro.tex +++ b/larics-git-tutorial-intro.tex @@ -18,7 +18,7 @@ \setbeamertemplate{itemize item}{\raisebox{0.25ex}{\small\textbullet}} \setbeamertemplate{itemize subitem}{\raisebox{0.25ex}{\scriptsize\textbullet}} \graphicspath{{figures/}} -\logo{\resizebox{10mm}{!}{\includegraphics{fer_logo.jpg}}} +\logo{\resizebox{10mm}{!}{\includegraphics{FER_logo}}} \setbeamersize{text margin left=15pt, text margin right=20pt} \setlength{\leftmarginii}{10pt} \setbeamertemplate{enumerate item}{ @@ -55,9 +55,9 @@ \author[Or\v{s}uli\'{c}, Mikli\'{c}]{Juraj Or\v{s}uli\'{c}, Damjan Mikli\'{c}} -\institute[LARICS]{LARICS Lab\\FER, University of Zagreb} +\institute[LARICS]{LARICS Lab\\University of Zagreb FER} -\date[]{December 2018} +\date[]{August 2021} %\AtBeginSection[] %{ @@ -90,7 +90,7 @@ \section*{Outline} % ============================================================================= -\input{branches.tex} +\input{collaboration.tex} % ============================================================================= @@ -102,7 +102,6 @@ \section{Where to go from here?} \begin{itemize} \item Install zsh and \href{http://ohmyz.sh/}{oh-my-zsh}, which provide awesome tab completion for git (branch names, commit IDs, git command options...) - \item When you have mastered the merge workflow from this presentation, read up on the rebase workflow described at the \href{http://larics.fer.hr/farm/laricswiki/doku.php?id=software:git}{LARICS git tutorial}, which enables you to produce much cleaner and linear commit history with fewer merges \end{itemize} Some additional literature: @@ -126,6 +125,7 @@ \section{Where to go from here?} \begin{frame} \begin{itemize} \item Super cool simulation for practicing advanced git branching: \\ \href{https://learngitbranching.js.org} {https://learngitbranching.js.org} + \item Next tutorial covering advanced topics such as \emph{rebasing} and \emph{subtrees} coming soon...ish :) \item If you have any questions, feel free to send an email to \href{mailto:juraj.orsulic@fer.hr}{juraj.orsulic@fer.hr}, or drop by LARICS (C-XI-16). \end{itemize} diff --git a/preparation.tex b/preparation.tex index 842c925..0545fa8 100644 --- a/preparation.tex +++ b/preparation.tex @@ -29,7 +29,7 @@ \section{Preparation} \frametitle{Preparing for the tutorial} \begin{itemize} - \item Open a \href{https://github.com/join?source=header-home}{GitHub account} and set up an SSH key for passwordless login according to \href{https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/}{these instructions on Github} + \item Open a \href{https://github.com/join?source=header-home}{GitHub account}\footnote{Another service like \href{https://gitlab.com}{GitLab} or \href{https://bitbucket.org/}{BitBucket} is also good if you already have an account there, just make sure to replace the corresponding URLs in the exercises.} and set up an SSH key for passwordless login according to \href{https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/}{these instructions on Github} \item Install the git command-line client and GUI tools \begin{minted}{console} > sudo apt install git git-gui gitg @@ -56,7 +56,6 @@ \section{Preparation} \frametitle{Tutorial organization} \begin{itemize} - \item Work in pairs \item Pair up with someone using the same programming language (C++ or Python) \item When assigning tasks and describing how you will interact with each other through git, we will refer to you, the members of a pair, as \textit{Mirko} and \textit{Slavko}. Make an agreement about who will assume each role. \end{itemize}