class: center, middle .logo[![](https://github.com/Academany/academany-mkt/raw/master/fabacademy2017/logo/fabacademy.png)] _January 22nd, 2018_ # Version Control **Fiore Basile** [fiore.basile@gmail.com](mailto:fiore.basile@gmail.com) .logo_tiny[ ![](https://github.com/Academany/academany-mkt/raw/master/fabacademy2017/logo/academany.png) ] --- background-image: url(images/versioncontrol.png) class: left, top # Agenda 1. Introduction 2. GIT 3. Getting started 4. Remote GIT 5. Advanced GIT 6. Hosted: Github and Gitlab 7. GLFS: Managing large files 8. References --- layout: true **1. Introduction** --- ## What is version control? .small-img[ ![](images/example1.png) ] --- ## Why version control? 1. Collaboration 2. Storing versions 3. Restoring changes 4. Finding out what changed 5. Making backups --- ## How to do VC - Copying files - Local version control - Remote (client-server) version control - Distributed version control --- ## Copying files - Save as.. - Incremental save .small-img[ ![](images/pdf_workflow.png) ] --- ## Local version control .tall-img[ ![](images/local.png) ]
Credit: ProGIT book
--- ## Remote version control .tall-img[ ![](images/clientserver.png) ]
Credit: ProGIT book
--- ## Distributed version control .tall-img[ ![](images/distributed.png) ]
Credit: ProGIT book
--- ## History and tools - Local - [SCCS](https://en.wikipedia.org/wiki/Source_Code_Control_System) - 70s - [RCS](https://www.gnu.org/software/rcs/) - 80s - Client server - late 80s - 90s - [CVS](http://www.nongnu.org/cvs/) - [Subversion](https://subversion.apache.org/) - Distributed - [Bitkeeper](http://www.bitkeeper.org/) - [Mercurial](https://www.mercurial-scm.org/) - [GIT](https://git-scm.com/) --- layout: true **2. .logo_micro[![](images/git.png)]** --- **History** GIT was born out of [necessity](https://github.com/torvalds/linux) - Bitkeeper was used for tracking the Linux Kernel - The company retired their free version - Linus Torvalds, creator of Linux, coded Git based on concepts borrowed from Bitkeeper .small-img[ ![](images/whygit.jpg)] [Merriam-Webster - Definition of git](https://www.merriam-webster.com/dictionary/git) *British : a foolish or worthless person* --- ### Snapshot vs Deltas .small-img[ ![](images/snapshots-vs-delta.png) ] Credit: [Batmat](http://batmat.github.io/presentations/git-next-level) --- ### Local operation .small-img[ ![](images/local_operation.png) ] --- ### Installation - Linux ```terminal $ sudo apt-get install git-all ``` -- - Mac ```terminal $ git ``` If you don't have it, OSX will ask you to install XCode Developer tools. If you want a new version [download it](http://git- scm.com/download/mac) from the main Git site and install like any other mac app. -- - Windows The best way to get started on Windows is to download [Github for Windows](http://windows.github.com) But really why? [Linux is better](http://distrowatch.com) --- layout: true ** 3. Getting started ** --- ### Knowing who you are Setting up your local identity ```terminal $ git config --global user.name "John Doe" $ git config —-global user.email "John@doe.com" ``` -- **git init**: Your first git repo ```terminal $ mkdir myproject $ git init Initialized empty Git repository in /Users/fiore/myproject/.git/ ``` -- **git add**: Tracking new files ```terminal $ vi test.txt $ git add test.txt ``` --- **git status**: Checking status ```terminal $ vi test2.txt // or notepad, textmate, sublime, any editor $ git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: test.txt Untracked files: (use "git add <file>..." to include in what will be committed) test2.txt ``` --- **git commit:**: Staging files ``` $ git commit -m 'adding the first files' [master c6bad0c] Adding the first files 1 file changed, 1 insertion(+) create mode 100644 test.txt ``` --- **.gitignore**: Ignoring files Not all files must be committed, i.e. passwords. Create a .gitignore file in the main folder to ignore them, i.e. for Mac ```terminal .DS_Store .AppleDouble .LSOverride ``` They won't show anymore in git status --- **git diff**: Finding out what you changed Edit one or more files, then check what you changed since the last commit ```terminal $ git diff test2.txt diff --git a/test2.txt b/test2.txt index b0b9fc8..835f9c0 100644 --- a/test2.txt +++ b/test2.txt @@ -1 +1,4 @@ Another file + + +This is the new content of the file ``` --- **git rm**: Removing files Don't simply delete files, tell GIT that you want them to be deleted during the next commit. Or **GIT will complain**. ```terminal $ git rm test.txt rm 'test.txt' $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: test.txt ``` Now commit to make change permanent --- ### Fixing errors If you deleted a file you didn't want to, you can restore it before committing ```terminal $ git checkout -- test.txt ``` If you deleted it with rm or with the GUI, tell git to delete it, using the --cached flag ```terminal $ git rm --cached test.txt ``` --- **git mv**: Moving files You can easily rename file, always using GIT ```terminal $ git mv test.txt newtest.txt $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: test.txt -> newtest.txt ``` Remember to commit changes to make permanent --- **git log**: Looking at the commit history ```terminal $ git log commit 23b66a4dfb36a01df0e13dc9de1115805697be73 Author: Fiore Basile <fiore.basile@gmail.com> Date: Mon Jan 22 14:10:03 2018 +0200 other edits commit c6bad0cb215d718c3818dc53d9d98faa767e0ee6 Author: Fiore Basile <fiore.basile@gmail.com> Date: Mon Jan 22 14:01:31 2018 +0200 Adding the first files commit 611838be215891bf5fb226ebbe9bfb135295b1bc Author: Fiore Basile <fiore@Fiores-MacBook.local> Date: Mon Jan 22 13:59:46 2018 +0200 Adding the first files ``` --- **git commit —amend**: Undoing changes If you forgot to add a file to a commit, but you don't want it to be in a new one, you can amend ```terminal $ git add forgot_this.txt $ git commit --amend [master 14d1929] renaming test Date: Mon Jan 22 14:13:06 2018 +0200 2 files changed, 2 insertions(+) create mode 100644 forgot_this.txt rename test.txt => newtest.txt (100%) ``` --- layout: true **4. Remote GIT** --- ### Remote repositories .tall-img[ ![](images/distributed.png) ] --- ### GIT Protocols: File You can store git repositories anywhere in your local computer. For example in a `/home/username/repos`folder. Then access it as ```terminal file:///home/username/repos/project.git ``` You can also omit the `file://` --- ### HTTP The most common protocol on the Internet (used by browsers) can be used to access remote repositories. An HTTP GIT url will look like: ```terminal https://example.com/gitproject.git ``` This protocol allows to use HTTPs (web encryption) and to use username and password for authentication. --- ### SSH The Secure Shell protocol is used to access remote computers on the internet in a secure manner. GIT can use this protocol as a transfer mechanism, and it's the default if you want to use public-key encryption instead of passwords. GIT repositories over ssh usually look like: ```terminal git@server:project.git ``` For access repositories you will need an **SSH-key pair**. More on this later. --- ### Working with remotes **git clone**: Cloning a repo Cloning a repository copies all the data (including history) from a remote GIT repository. Cloning the main Fab Academy 2018 archive website for example: ```terminal git clone git@gitlab.fabcloud.org:academany/fabacademy/2018/site.git | aha -b -n | pbcopy Cloning into 'site'... Enter passphrase for key '/Users/fiore/.ssh/id_rsa': remote: Counting objects: 122, done. remote: Compressing objects: 100% (70/70), done. remote: Total 122 (delta 65), reused 92 (delta 48) Receiving objects: 100% (122/122), 78.26 KiB | 348.00 KiB/s, done. Resolving deltas: 100% (65/65), done. ``` A password was asked since I have one in my private key You only clone _once_ --- **git remote show**: listing remote repositories To know which remote repositories are _tracked_ by your local repository, you can use the git remote command ```terminal $ git remote show origin ``` And then you can get all the details, specifying the name of the remote ```terminal $ git remote show origin * remote origin Fetch URL: git@gitlab.fabcloud.org:academany/fabacademy/2018/site.git Push URL: git@gitlab.fabcloud.org:academany/fabacademy/2018/site.git HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date) ``` This command will connect to the remote, so it might ask your SSH identity password, and won't work offline --- **git remote add**: adding a remote If you create a project locally, and then want to _push_ it on Github or Gitlab, you must add it as a remote first. ```terminal $ git remote add origin git@gitlab.fabcloud.org:fibasile/myproject.git ``` --- **git fetch**: fetching changes To sync your local repository with changes done on a remote one by you or other users you have two options: ```terminal $ git fetch remote: Counting objects: 3, done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 2), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From gitlab.fabcloud.org:academany/fabacademy/2018/site 3cc2a3b..df615c0 master -> origin/master ``` --- This won't do anything to your local repository files. You must merge the changes to see them. ```terminal $ git merge origin master Updating 3cc2a3b..df615c0 Fast-forward README.md | 2 ++ 1 file changed, 2 insertions(+) ``` --- **git pull**: fetching changes and merging If you want also to update your local repository you must _pull_, specifying the name of the remote and the _branch_ ```terminal $ git pull origin master remote: Counting objects: 3, done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 2), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From gitlab.fabcloud.org:academany/fabacademy/2018/site * branch master -> FETCH_HEAD df615c0..9d8ad88 master -> origin/master ``` As you see this is just a combination of git fetch and git merge commands --- **git push**: pushing changes to a remote repository Once you have committed your work, it's easy to sync it with a remote repository: ```terminal $ git push origin master Counting objects: 16, done. Delta compression using up to 4 threads. Compressing objects: 100% (16/16), done. Writing objects: 100% (16/16), 742.22 KiB | 16.87 MiB/s, done. Total 16 (delta 1), reused 0 (delta 0) To gitlab.fabcloud.org:academany/fabacademy/2018/site.git 9d8ad88..78bf52d master -> master ``` This will syncronize your local _master_ branch with the _origin_ branch called _master_ --- layout: true **5. Advanced GIT** --- **git tag**: tagging commits If you need to find a specific commit (i.e. version) of your repository easily, perhaps to restore it later, you can use tags: ```terminal $ git tag version_control_recitation ``` To list tags you use: ```terminal $ git tag show version_control_recitation ``` --- Then you can restore that specific version with ```terminal $ git checkout version_control_recitation Note: checking out 'version_control_recitation'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b
HEAD is now at 78bf52d... version control slides ``` To make changes is now necessary to make a branch --- **Branching** - Branches allow to develop in parallel different versions of the repository. - Imagine a branch as a snapshot of your current files - You can have as many branches as you want and switch between them - You start with a _master_ branch - You have one branch active at a time .small-img[ ![](images/branching.png)] --- **git branch**: create a branch ```terminal $ git branch develop $ git checkout develop Switched to branch 'develop' ``` You create a branch, and to work with it you must _checkout_ it. From now on, all commits will go to the _develop_ branch, not on _master_. You can switch between the two using the **checkout** command. Just make sure you committed all the changes in the current branch before switching. --- **git checkout -b**: create a branch and checkout it You can create a branch and checkout it in one go. Just use the -b option ```terminal $ git checkout -b testme Switched to a new branch 'testme' ``` --- **Creating remote branches** You can also create branches on remote repositories, based on your local branches and vice versa. In our example: ```terminal $ git push origin develop Counting objects: 13, done. Delta compression using up to 4 threads. Compressing objects: 100% (8/8), done. Writing objects: 100% (13/13), 1.07 KiB | 546.00 KiB/s, done. Total 13 (delta 0), reused 0 (delta 0) To gitlab.fabcloud.org:fibasile/myproject.git * [new branch] develop -> develop ``` --- **Merging** Once you are happy with the changes made to a branch, you can _merge_ your change into another, possibly the _master_ branch or any others. Merging a branch means bringing all the changes on top of your current ones, and can possibly create **conflicts** --- **git merge**: merging another branch To merge a branch, you checkout the target one and use the git merge command. ```terminal $ git checkout develop Switched to branch 'develop' $ vi README.txt $ git add README.txt $ git commit -m 'adding readme' [develop 4176457] adding readme 1 file changed, 1 insertion(+) create mode 100644 README.txt $ git checkout master Switched to branch 'master' $ git merge develop Updating 14d1929..4176457 Fast-forward README.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.txt ``` A Fast Forward merge is when there's no intermediate commits interesting the changed files. Git internally simply forwards a pointer to the new snapshot. --- **git pull**: merging a remote branch As seen before when _pulling_ a remote repository we specify a _branch_. So for example we can directly merge our remote _develop_ branch into our local master, etc ```terminal $ git pull origin develop ``` --- **Conflicts** When more of one user works on the same file, editing the same lines, a Fast forward merge is not possible. **Creating a conflict** For example If you edit the README.txt on the remote repository and the local repository, committing on both your changes: ```terminal $ git pull origin master remote: Counting objects: 3, done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From gitlab.fabcloud.org:fibasile/myproject * branch master -> FETCH_HEAD 4176457..019189a master -> origin/master Auto-merging README.txt CONFLICT (content): Merge conflict in README.txt Automatic merge failed; fix conflicts and then commit the result. ``` --- **Fixing conflicts** You must solve the conflict manually editing the README.txt Git will help you telling what is changed locally and remotely. ``` <<<<<<< HEAD No this is not true Added readme ======= Added a new file called README >>>>>>> 019189a6a41e8c015459290ca19d8c4955a16baa ``` Just delete what is wrong and change the file the way it should be. --- **Committing your changes** Add the changed files and commit them as usual, then push ```terminal $ git add README.txt $ git commit -m 'Solved merge' [master e830465] Solved merge $ git push origin master Counting objects: 4, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (4/4), 565 bytes | 565.00 KiB/s, done. Total 4 (delta 0), reused 0 (delta 0) To gitlab.fabcloud.org:fibasile/myproject.git 019189a..e830465 master -> master ``` --- **Rebasing** - Rebasing follows a different strategy compared to merging. - Instead of creating a new commit using a three way merge of two branches - You can take all the changes that were committed on one branch and replay them on another one ```terminal $ git checkout develop Switched to branch 'develop' $ git rebase master First, rewinding head to replay your work on top of it... Fast-forwarded develop to master. ``` - This way basically you rewrite the GIT commit log joining all the changes in a single commit --- **When to Rebase vs Merge** Do not rebase commits that exist outside your repository. - Only rebase local merges that you have not pushed remotely - Never rebase something that you have pushed somewhere --- **Workflows** - **Default**: you work on the master branch, and just tag commits, good for simple projects - **Feature or Topic branches**: you create a new branch any time you want to add a new feature, when you are ready you sync the master branch and delete the feature branch - **Long-living branches**: in some projects you want to have a master branch holding the development version, a production branch for the version used by customers, and a bugfix branch to fix bugs. Bugfixes become production, till development version reaches maturity - **Remote branches**: you can mix the two strategies with local branches for features and long living branches on remote repository. You can also use different repositories for production and development. --- layout: true **6. Hosted GIT** --- ### Github - Registering - Adding your SSH Key - Forking - Pull Requests --- ### Gitlab - Adding your SSH Key - Creating projects - Setting up Gitlab CI - Issue Tracking - Wiki - Gitlab Goodies --- layout: true **7. GIT LFS** --- ## Why Git LFS? .small-img[ ![](images/lfs.png) ] GIT works really bad with large files --- ## How to use - [Download](https://git-lfs.github.com/) the package and install it - Install it ```terminal git lfs install ``` --- - Select the file types you'd like Git LFS to manage, add and commit .gitattributes ```terminal git lfs track "*.mp4" git add .gitattributes git commit -m 'add files' git push origin master ``` GIT LFS uses http to transmit files, so you must use your username and password for it. Update an existing repository ```terminal git lfs fetch master ``` --- layout: true **8. Credits and references** --- ### Images from ProGIT Book This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. ### References - [Git - Book](https://git-scm.com/book/en/v2) - [NDP Software :: Git Cheatsheet](https://ndpsoftware.com/git-cheatsheet.html) - [Try GIT](https://try.github.io/) - [Take Your Git Practice To The Next Level](http://batmat.github.io/presentations/git-next-level/prez.html)