1 of 93

Git Tutorial

Arctos 6135

2 of 93

Basic Concepts

3 of 93

What is a Version Control System (VCS)?

  • Also known as Source Code Management (SCM)
  • Helps you keep track of changes to files (usually code but doesn’t have to be)
  • Easily go back to an older version in case of a screw-up
  • Also allows you to work on multiple things at a time
  • Similar to taking frequent backups, but much more efficient and powerful

4 of 93

What is Git?

  • A popular, open source VCS made by Linus Torvalds (same guy who made Linux)
  • Decentralized - every repository is created equal, no “central” repository
  • Saves history as snapshots instead of differences
  • A command-line program with no official GUI
  • Git ≠ GitHub!

5 of 93

The Need For Git/VCS

  • How do we track collaboration across multiple contributors and files?
  • How do we experiment with a new feature without the risk of breaking something?
  • How do we know which is the right one, robot_2018_working_RIGHT_ONE_1.zip or robot_2018_working_RIGHT_ONE_FINAL.zip?
  • When used properly, a VCS solves all of these problems.

6 of 93

Installation

7 of 93

Installation

  • Go to https://git-scm.com/downloads for Windows and Mac versions
  • On most Linux distros, you can install through the package manager

If that doesn't fix it, git.txt contains the phone number of a friend of mine who understands git. Just wait through a few minutes of 'It's really pretty simple, just think of branches as...' and eventually you'll learn the commands that will fix everything.�Source: https://xkcd.com/1597/

8 of 93

For Windows Only:

  • Use the default Windows cmd.exe
  • Change editor to VS Code

9 of 93

Git Basics

10 of 93

Getting a Git Repository

  • Everything you do with Git has to be inside a repository (like a project)
  • To create a repository, create a directory and run git init
  • Or, to download an existing repository, use git clone
  • E.g. git clone https://github.com/Arctos6135/frc-2019.git
  • Note that cloning automatically creates a directory with the default name for you, or you can specify it with git clone <URL> [name]

11 of 93

Tracked vs Untracked Files

  • Git does not keep track of everything; files can be tracked or untracked

12 of 93

Tracked vs Untracked Files (contd.)

  • Untracked: Git does not care about what happens to it
  • Unmodified: Git is tracking the file, and the file has not changed since the last snapshot
  • Modified: Git is tracking the file, and the file has changed, but the change will not be added to the next snapshot
  • Staged: Git is tracking the file, and the file has changed, and the new changes will be in the next snapshot

13 of 93

Checking File Status

  • Use git status to check the status of your files

14 of 93

Tracking and Staging Files

  • Use git add to start tracking a new file, or to stage a modified file

15 of 93

Tracking and Staging Files (contd.)

  • E.g. git add newfile will start tracking newfile or stage its changes
  • You can add multiple files at a time, e.g. git add newfile1 newfile2 adds both files
  • You can also use git add --all to add all files
  • Use with care! Some files should not be tracked (more on that later)

16 of 93

Commits (Snapshots)

  • At the heart of Git, commits are snapshots of your work
  • Each commit has a parent, creating a chain/tree
  • Later you’ll learn that commits can have multiple parents and children

17 of 93

Commits (Snapshots) (contd.)

  • Every time you make a commit, Git stores a new copy of all the files that changed
  • Every commit is associated with a unique SHA-1 hash, used to identify and reference that commit
  • Every commit also has a message so you can easily tell what changed
  • Committing is done with git commit (more on that later)

18 of 93

Creating Commits

  • Before you commit, make sure to git add to stage changes!
  • Only staged changes will be included in the commit
  • git commit opens the commit message editor
  • Once you close the editor, the snapshot is taken
  • Alternatively, git commit -m “message” (not recommended)
  • git commit -a automatically stages all changes (but does not include any new files)

19 of 93

Writing Good Commit Messages

  • Good commit messages make life easier for others and your future self
  • Check out https://chris.beams.io/posts/git-commit/

Merge branch 'asdfasjkfdlas/alkdjf' into sdkjfls-final�Source: https://xkcd.com/1296/

20 of 93

Viewing the Commit History

  • You can look at the commit history using git log
  • By default it shows the full commit hash, author, date and full message

21 of 93

Viewing the Commit History (contd.)

  • You can pass options to git log to change what is shown
  • --all: show all branches
  • --oneline: use one line for each commit
  • --graph: draw a commit graph using ASCII art

22 of 93

The 3 Areas of Git

  • There are 3 areas in Git - the Working Directory, Staging Area and the Repository (.git directory)
  • The Working Directory�contains all the files you’re�currently working on
  • The Staging Area contains all�staged (added) changes
  • The Repository contains all�the snapshots in the form of�commits

23 of 93

Undoing Things

24 of 93

Fixing Commit Mistakes

  • The point of a VCS is to make fixing mistakes easy
  • If you forgot to stage a file before committing, or forgot to make a change, you can use git commit --amend
  • You can also use it to change the commit message
  • E.g.�git commit -m "Missed a file in this commit"git add missed_file�git commit --amend

25 of 93

Un-modifying a Modified File

  • If you modified a file but have not committed it, you can discard the changes using git checkout -- <file>
  • Note that there’s a space between the -- and the filename
  • You can also use git reset --hard HEAD to discard the changes to ALL files
  • Use with care! There is NO going back!

26 of 93

Undoing Commits - Method 1 (Revert)

  • If you want to undo a commit, there are 3 different methods you can use.
  • The first method is using git revert <commit> where <commit> is the hash
  • This creates a new commit that undoes the bad commit

Still Accessible

27 of 93

HEAD and master (References)

  • The next two method works by moving references
  • HEAD and master are references pointing to commits
  • HEAD is the current commit you’re on
  • master is the branch tip, think of it as the most recent commit

HEAD

master

28 of 93

Undoing Commits - Method 2 (Reset)

  • The second way to undo changes is to use git reset
  • This moves HEAD and the current branch reference (for now, master)
  • History is permanently lost!

HEAD

master

HEAD

master

Inaccessible

Lost Forever*!

29 of 93

Hard, Soft and Mixed Resets

  • There are three types of resets: --hard, --soft and --mixed (which is the default)
  • All 3 resets change HEAD and the current branch reference (for now, master), resulting in lost history
  • Hard resets does not keep anything - everything is lost
  • Soft resets keeps the changes and stages them - history is lost, but code is kept
  • Mixed resets keeps the changes but does not stage them - again, history is lost, code is kept

30 of 93

Undoing Commits - Method 3 (Checkout)

  • The third way to undo commits is to use git checkout
  • This only changes HEAD and is usually temporary
  • No history is lost as commits are still accessible

HEAD

master

HEAD

Still Accessible

31 of 93

Detached HEAD

  • Once you check out a commit, you will be in ‘Detached HEAD’ state - HEAD is not pointing to any branch
  • To go back, do git checkout master (or another branch)
  • Later you’ll learn that you can also create a branch from here

32 of 93

Ignoring Files

33 of 93

What Files Should Not Be Tracked

  • Not all files should be tracked!
  • Git is not good at keeping track of binaries (non-text files)
  • In general, you should not track files that are generated (e.g. compiled code binaries, log files, etc.)
  • Also leave out local configuration files (i.e. config files that are only useful to you)
  • For example, track MyClass.java, but not MyClass.class

34 of 93

The .gitignore File

  • Use this special file to hide files from Git
  • The files listed in the .gitignore file will be ignored by Git completely
  • Ignored files cannot be tracked, not even explicitly through git add
  • The .gitignore file itself is generally tracked

35 of 93

.gitignore Syntax

  • .gitignore files use Regexes; every line is a new filename pattern
  • You can specify the exact name of a file or directory, such as .gradle or bin
  • You can add a slash to the end of a pattern to only match directories; e.g. bin/ will only match the directory bin and not the file bin

36 of 93

.gitignore Syntax (contd.)

  • You can use a leading slash to anchor the search to the root; e.g. /bin will match bin in the top level directory, but not foo/bin
  • Use * for wildcards; e.g. *.class will match all files with the .class extension
  • Lines starting with a # are ignored (comments)

37 of 93

Ignoring Already Tracked Files

  • If a file is already being tracked, putting it in the .gitignore will not automatically untrack it
  • After putting it in the .gitignore you must run git rm --cached <file> or git rm --cached <directory>

38 of 93

.gitignore Templates

  • You can find sites that offer .gitignore templates, such as gitignore.io, github/gitignore, etc.
  • Use them as templates; often you’ll want to customize them to suit your specific needs

39 of 93

Branching

40 of 93

What are Branches?

  • Branches allow you to diverge from the main line of development and do something else
  • You can have multiple commits with the same parent commit, which essentially “branch off” separately

41 of 93

Branches in Git

  • Technically speaking, branches in Git are nothing more than references pointing to commits
  • The name master is not special; it’s just the default
  • (HEAD is not a branch)

master

branch1

42 of 93

Creating and Deleting Branches

  • Use git branch <name> to create a new branch pointing to the current commit with the specified name
  • Use git branch -d <name> to delete a branch

HEAD

master

git branch newbranch

newbranch

43 of 93

Viewing Branches

  • Use git branch without any arguments to view all the branches:

  • The * denotes the current branch

44 of 93

Switching Between Branches

  • As previously mentioned git checkout changes HEAD
  • Use it to change branches: git checkout <name>

HEAD

master

git checkout newbranch

newbranch

HEAD

45 of 93

Switching Between Branches (contd.)

  • Alternatively use git checkout -b <name> to create a branch and switch to it at once

HEAD

master

git checkout -b newbranch

newbranch

HEAD

46 of 93

Branching Example

  • Here’s an animation showing branching:

HEAD

master

git checkout -b newbranch

newbranch

HEAD

git commit

newbranch

HEAD

git checkout master

HEAD

master

47 of 93

Merging

48 of 93

What is Merging?

  • Now that you have multiple branches with different changes, merging combines changes from different branches

49 of 93

How to Merge Branches

  • Use git merge <branch> to merge another branch into the current branch
  • E.g. If you’re on master and you run git merge develop, develop will be merged into master, creating a single commit that combines both branches*
  • The branch that’s being merged is not modified; the branch that’s being merged into is

*A merge commit will not be created if it’s a fast-forward (more on that later)

50 of 93

Fast-Forward Merges

  • The branch being merged is a direct child of the current
  • No merge commit is created; the refs are simply moved

master

git merge master

newbranch

HEAD

newbranch

HEAD

51 of 93

Merging Divergent Branches

  • When two divergent branches are merged, a merge commit is created: (HEAD not shown for sake of simplicity)

master

newbranch

git merge newbranch

master

52 of 93

Merge Conflicts

  • Merging doesn’t always go successfully
  • Git can usually automatically combine changes
  • However if the two branches modified the same sections of code differently a merge conflict will happen
  • Git will not know what changes you want to keep

53 of 93

Resolving Merge Conflicts

  • When a merge conflict happens, Git will put the changes from both branches into the file with the conflict
  • They’re marked with <<<<<<< ref, ======= and >>>>>>> ref
  • Visual Studio Code can detect them automatically and provides useful shortcuts

54 of 93

Resolving Merge Conflicts (contd.)

  • When you’ve resolved the conflicts in a file, you can git add it to mark it as resolved
  • When you’ve resolved and added all the files, just do a git commit like normal to make the merge commit

55 of 93

Merge Strategies

  • When merging divergent branches, you can tell Git to use different “strategies”
  • Use git merge -s <strategy> <branches>
  • Common Strategies:
    • recursive: default when merging two branches
    • octopus: default when merging more than two branches
    • ours: ignores all changes from other branches, useful for cleaning up branches without losing history
  • There is no “theirs” option, instead use git merge -X theirs <branches>

56 of 93

Remotes

57 of 93

What are Remotes?

  • Remotes are versions of your repository that are hosted somewhere else
  • They can be on the internet, e.g. GitHub, on the same machine, or even on a USB key (very useful at comps)
  • To see your remotes, use git remote
  • Repositories that are cloned automatically have a remote named origin
  • Again, there’s nothing special about that name, it’s just the default

58 of 93

Adding Remotes

  • You can add new remotes using git remote add <name> <url>
  • The URL is usually provided by a hosting service like GitHub
  • It can also be a path to a file on the local system, e.g. /home/username/somerepo
  • E.g. git remote add origin https://github.com/Arctos6135/frc-2019.git

59 of 93

Fetching From a Remote

  • git fetch <remote> [branch] downloads all the data from the remote that you don’t already have
  • This data is fetched and put into branches
  • This creates/updates branches with the name <remote>/<branch>
  • To update your own branches do a merge
  • These fetched branches are special; you can’t see them through git branch (but you can with git branch -a)

60 of 93

Pulling From a Remote

  • git pull <remote> [branch] fetches from the remote and updates your branches in a single step
  • Note that it will only do the merging for your current branch; it will only fetch for other branches

61 of 93

Pushing to Remotes

  • git push <remote> [branch] updates the remote’s branches with your current changes
  • Note that the remote will reject non-fast-forwards (more on that later)

62 of 93

Deleting Branches on a Remote

  • You can delete a branch on a remote using git push -d <remote> <branches> or git push --delete <remote> <branches>
  • You can also do it using git push <remote> :<branch>, e.g. git push origin :feature deletes the “feature” branch

63 of 93

Remotes and Merge Conflicts

  • As remotes can be thought of as branches, they can have merge conflicts too
  • To prevent a merge conflict on the remote, it will reject anything that’s not a fast-forward
  • This means that if someone else pushes before you do, you have to pull down their changes first
  • Likewise when you pull down changes, there may be merge conflicts

64 of 93

Force-Pushing

  • As the remote will reject non-fast-forwards, amending a pushed commit and trying to re-push it will result in failure
  • You can do a force push using git push -f to tell the remote to accept your changes no matter what
  • However this will overwrite others’ pushed work, so avoid using it when you’re collaborating with others

65 of 93

Tracking and Upstream Branches

  • Tracking branches have a direct relationship to a remote “upstream” branch
  • With tracking branches, you can directly do git pull or git push without specifying which remote or branch
  • To track a remote branch, set the upstream using git branch -u <remote>/<branch> (or --set-upstream-to)
  • Git will also automatically create a tracking branch when you try to checkout a branch with the same name

66 of 93

Tagging

67 of 93

What are Tags?

  • Tags are references, just like branches
  • However unlike branches they do not move
  • They’re good for marking important things, e.g. releases

HEAD

master

v1.0

HEAD

master

68 of 93

Lightweight vs Annotated Tags

  • Lightweight tags only have a ref and a name
  • Annotated tags also have a message, along with a tagger and date

69 of 93

Creating & Deleting Tags

  • To create lightweight tags, use git tag <name> [commit]
  • To create annotated tags, use git tag -a <name> [commit]
  • You can also use the -m <message> option to specify an inline message
  • By default Git will tag the current commit, but you can also specify a commit hash
  • To delete a tag, use git tag -d <name> or git tag --delete <name>

70 of 93

Viewing Tags

  • To list all the tags, use git tag --list or just git tag
  • You can also search for tags with wildcards, e.g. git tag --list "v1.*"
  • To view a specific tag, use git show <name>
  • Viewing a lightweight tag will show the commit, but viewing an annotated tag will also show the tag info

71 of 93

Pushing & Deleting Tags in a Remote

  • By default, when you do a git push tags are not pushed
  • You have to explicitly do git push <remote> <tag> just like pushing regular branches
  • You can also do git push --tags to push all tags at once
  • You can delete a remote tag the same way you delete a remote branch, i.e. with git push -d or the colon syntax

72 of 93

Stashing

73 of 93

What are Stashes?

  • Stashes allow you to temporarily save your work without a commit
  • Use a stash to clean up your working directory so you can work on something else
  • This avoids making a commit with broken/unfinished code
  • Stashes are stored on a stack (LIFO)
  • Stashes cannot be pushed to a remote!

74 of 93

Using Stashes

  • Use git stash or git stash push to stash changes (untracked files aren’t stashed)
  • Use git stash pop to apply (and drop/delete) the last stash
  • Or, use git stash apply to apply it without dropping
  • Use git stash list to show all the stashes
  • Use git stash drop to drop (delete) the last stash
  • Use git stash clear to drop all stashes

75 of 93

Stash Messages

  • Stashes can also have messages to describe what they do
  • Use git stash push -m <message> to specify a message
  • If a message isn’t specified, the message of the last commit will be shown

76 of 93

Stash Names & Hashes

  • Note how every stash has a name (e.g. stash@{0})
  • This name can be used to operate on a specific stash
  • E.g. git stash apply stash@{1} applies the second stash
  • Each stash also has a hash which can be used in the same way
  • Using the hash one can recover a dropped stash

77 of 93

The Branching Model/Workflow

78 of 93

What is a Branching Model/Workflow?

  • Branching models are a set of guidelines about how you should use branches
  • They tell you when to branch and merge, how to name branches etc.
  • They keep the branches organized and the history clear
  • They help with collaboration

79 of 93

Our Branching Model

  • The branching model we use can be found here: https://nvie.com/posts/a-successful-git-branching-model/
  • Also in the Guide to Code Contribution (2019-2020)
  • Essentially, there are two long-lasting branches: master and develop
  • master should contain good, stable working code at all times
  • develop contains the latest delivered changes

80 of 93

Our Branching Model (contd.)

  • Any time there’s a new feature, do it on a new branch coming off of develop
  • When the feature is completed, merge it back into develop
  • When the code in develop is stable and can be released, merge it into master
  • Only develop may be merged into master
  • develop and (especially) master should only contain merge commits

81 of 93

A Note on Merging

  • When merging, use the --no-ff flag to avoid fast-forwards and create a merge commit no matter what

master

develop

master

82 of 93

A Note on Merging

  • When merging, use the --no-ff flag to avoid fast-forwards and create a merge commit no matter what

master

develop

master

83 of 93

GitHub

84 of 93

What is GitHub?

  • A version control hosting service using Git
  • GitHub is not Git! GitHub only hosts Git repositories
  • Not the only option; many alternatives exist
  • A powerful tool for collaboration

85 of 93

GitHub as a Remote

  • Most often GitHub is used as a central remote to push/pull commits from
  • The entire team pushes and�pulls from a single central�repository on GitHub
  • Team members can clone the repo�hosted on GitHub and work on it�from anywhere

86 of 93

Creating a Repository

  • You can also create�your own repository�on GitHub
  • We won’t go into�details about this since it’s pretty simple and most often you’ll have an existing repository to work with

87 of 93

Issues

  • Every repository has an Issue Tracker - a place to track bugs, features and other things that need to be done
  • They can be assigned to specific people
  • Anyone can open an Issue on a public repository, not just the owners
  • You can use it to report bugs, request or track features, and manage tasks

88 of 93

Issues (contd.)

  • You can comment on issues to discuss them with team members
  • Issues are closed when they are done, e.g. the bug was fixed or the feature implemented
  • Every issue has a number, e.g. #23, which we use to reference it (works in commit messages too)

89 of 93

Pull Requests

  • Pull Requests (PRs) are similar to Issues
  • They track the merging of one branch into another
  • They also allow for discussion and task management
  • They’re also referenced using a number, e.g. #36, and share the same counter as issues

90 of 93

Pull Requests (contd.)

  • PRs can be merged or closed without merging
  • Submitting a PR (instead of directly merging and pushing) allows others to review your changes and make sure they’re adequate
  • PRs can show you what�changed and provide an�interface for code review

91 of 93

Forks and Contributing to Open Source

  • Forks and PRs allow you to contribute to open-source projects that you don’t own
  • Forking creates a copy of the repository under your name that you can modify to add your changes
  • Once you’re done adding changes, submit a PR to merge your fork back into the original repository
  • This model also works within�a team as well

92 of 93

Works Cited

93 of 93

Works Cited

  • Pro Git V2” by Scott Chacon and Ben Straub CC BY-NC-SA 3.0