layout: true name: theme <p class="my-footer"><a href="https://github.com/prncevince/using-git"><span>by vincent clemson</span></a></p> --- class: title-slide inverse split-50 <h1 class="title">Version Control - Using Git</h1> .row[.center.vbottom-0[ for an overview - press 'o' ]] <h3 class="author">vincent clemson</h3> <img class="topic" src="assets/img/topic.png"> --- layout: true template: theme name: theme <p class="my-header" id="my-header"><span>Version Control - Using Git</span></p> --- class: split-25 .row[.left.vtop-0[ # .x250.advent-pro[What is VERSION CONTROL?] ]] .row[.split-two[ .column[.vmiddle.padding-left-5.padding-top-5.font_large.nooverflow.content[ The practice of tracking and managing changes to software code. <br><br> Version control systems (e.g. [Git](https://git-scm.com)) are tools that help software teams manage changes to source code. ]] .column[ .bg-deep-orange.center.hleft-5.content[ <img style="max-width:77%" src="assets/img/dvcs.png"> ]]]] --- class: split-33 .row[.center.vmiddle[ # .x250.advent-pro[Preface] ]] .row[.split-33[ .column[.vtop-5.hleft-5.font_large.content[ You will mess up - It's okay to mess up - ... [`git`](https://git-scm.com/docs/git) is stupid ]] .column[ .vtop-5.hleft-5.font_large.bg-brown.white.content[ `man`<code class="remark-inline-code" style="color: var(--color-deep-orange)"> git</code> : > GIT(1) Git Manual GIT(1)<br><br> **NAME**<br> .hleft-15[git - the stupid content tracker<br><br>] ]]]] --- class: middle center # .x300.advent-pro[Setup] --- # Installing Git & Friends ## Windows OS - [Git for Windows](https://gitforwindows.org) - Unix-like [Terminal Emulator](https://esgovcloud.com/mAndA/savi/blob/master/CONTRIBUTING.md#windows-10) - Use a Windows package manager like [choco](https://chocolatey.org), [scoop](https://scoop.sh), or [winget](https://github.com/microsoft/winget-cli) ## macOS (Unix-like) - you should already have `git` installed - Using [Homebrew](https://brew.sh) to upgrade - `brew install git` - You can use Terminal.app ... or something like [iTerm2](https://www.iterm2.com/index.html) ## Linux - Different depending on your distro - ... you should know how to install packages --- class: nomargin-ul .pull-left[ # SSH Keys ### Resources - [Connecting to GitHub with SSH](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) - [GitLab and SSH keys](https://docs.gitlab.com/ee/ssh/README.html) ### Steps - Generate an SSH public/private key pair<br> \> `ssh-keygen` - Start SSH Agent<br> \> ``eval `ssh-agent -s` `` - Add SSH private key to SSH agent<br> \> `ssh-add` - Add public key to repository (GitHub/GitLab)<br> macOS:<br> \> `pbcopy < ~/.ssh/id_rsa.pub`<br> Windows:<br> \> `cat ~/.ssh/id_rsa.pub | clip` - Test connection<br> \> `ssh -T git@esgovcloud.com` - Clone private repository<br> <code class="remark-inline-code x75"> \> git clone git@esgovcloud.com:mAndA/clone-me.git </code> ] .pull-right[ ### ~/.profile [~/.bash_profile, ~/.bashrc, ~/.zshrc] ```bash # Logout exit_session() { . ~/.bash_logout } # SSH Agent if [ -z "$SSH_AUTH_SOCK" ] ; then eval `ssh-agent -s` trap exit_session SIGHUP fi ``` ### ~/.bash_logout or ~/.zlogout ```bash # SSH Agent if [ -n "$SSH_AUTH_SOCK" ] ; then eval `ssh-agent -k` fi ``` ] --- class: split-two m1 .column[.content[ # SSH Config ### .center[~/.ssh/config] ```bash Host github.com github HostName gitlub.com User git IdentityFile ~/.ssh/id_rsa PreferredAuthentications publickey AddKeysToAgent yes VisualHostKey yes Host esgovcloud.com esgovcloud HostName esgovcloud.com User git IdentityFile ~/.ssh/id_rsa PreferredAuthentications publickey AddKeysToAgent yes VisualHostKey yes ``` ]] .column[.content[ ### .center[Usage] `ssh -T esgovcloud`<br> `ssh -T github`<br> etc ... ### .center[Another Example] .center[<img style="max-width: 52%" src="assets/img/ssh-config.png">] ]] --- class: split-two m1 .column[.content[ # Git Config ### ~/.gitconfig ```bash git config --global user.name "First Last" git config --global user.email "hi@gmail.com" ``` ]] .column[.content[ # ### Docs [8.1 Customizing Git - Git Configuration](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration)<br> `git config --help` ]] --- class: split-10 m1 nopadding-h2 nomargin-pre nomargin-h4 .row.center[ # 2 Methods - Getting Started ] .row.split-two[.column[.content[ ## Brand New Repo #### Initialize Repo ```bash git init ``` #### Adding a local git config ```bash git config user.email "first.last@perspecta.com" ``` #### Adding a remote repository ```bash git remote add origin git@esgovcloud.com:mAndA/your-unique-test-repo.git ``` #### Track Files ```bash git add ``` #### Commit Changes ```bash git commit -m "track files, first commit\!" ``` #### Push to Remote Repo ```bash git push -u origin master ``` ]] .column[.content[ ## Preexisting Repo #### Cloning ```bash git clone git@esgovcloud.com:mAndA/clone-me.git ``` .img-contain[![](assets/img/clone-button.png) ] ]]] ??? Demo by creating a new repo. Then, delete it. --- class: m1 split-two .column[.content[ # R Project + RStudio + Git RStudio Support Guide: - [Using Projects in R / RStudio](https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects) ![](assets/img/project-1.png) ![](assets/img/project-2.png) ]] .column[.content[ ![](assets/img/project-3.png) ![](assets/img/project-4.png) ]] ??? Demo with https://esgovcloud.com/mAndA/clone-me. --- class: middle center # .x300.advent-pro[Basic Concepts & `Commands`] --- class: m1 split-two .column[.content[ # <center>"3 Trees"</center> Keeps a timeline of edits in Git. [Resource](https://www.atlassian.com/git/tutorials/undoing-changes/git-reset) .center[![](assets/img/three-trees-scaled.svg)] ]] .column[.content[ ### Working Directory I am editing/changing a file named `10-three-trees.Rmd` in the folder containing a Git repo. <img src="assets/img/three-trees-1.png" style="max-width:60%"> ### Staging Index Next, let's make Git "track" these changes. <img src="assets/img/three-trees-2.png" style="max-width:60%"> ### Commit History / HEAD / Repo Finally, let's "commit" these changes. <img src="assets/img/three-trees-3.png" style="max-width:60%"> ]] --- class: m1 split-two .column[.content[ # [`git init`](https://git-scm.com/docs/git-init) Creates an empty Git repository. <br> Creates directory `./git/` where all data in Git repo is stored. <br> .center[<img src="assets/img/git-init.png" style="max-width:53.5%">] ]] .column.split-three[.row[.vmiddle[ ### .center[When to run `git init`?] Run when first creating a repo. Not after it's been made. ]].row[.vmiddle[ ### .center[**WHEN** Though?] As soon as you can. The more you procrastinate, the more the never you will use Git! ]].row[.vmiddle[ ### .center[How do I delete my git repo?] Delete the `./git` directory. <br> e.g. `rm -rf .git` ]]] --- class: m1 split-two .column[.content[ # [`git add`](https://git-scm.com/docs/git-add) Adds new files to the staging index. <br> Once added, Git tracks changes ("modifie̶d̶"-cations) to these files. These changes can be committed. <br> .center[<img src="assets/img/git-add.png" style="max-width:100%">] ]] .column[.content[ ### .center[When to run `git add`?] Run when you add new files to your repo. ### .center[How do I `add` an empty folder?] Create an empty hidden file in your empty folder! <br> e.g. `touch my-empty-folder/.keep` <br> ^ It'll show up on Git-Hub/Lab 🎉🥳! ### .center[How do I **IGNORE** files/folders?] Create a `.gitignore` & add paths to it. [Reference](https://git-scm.com/docs/gitignore) <br> .center[<img src="assets/img/gitignore.png" style="max-width:100%">] ]] --- class: m1 split-two .column[.content[ # [`git commit`](https://git-scm.com/docs/git-commit) Records changes ("modifi.x75[e̶d̶]"-cations) to tracked files. <br> Logs them as a "commit" in Git repo. <br> .center[<img src="assets/img/git-commit.png" style="max-width:73.5%">] ]] .column[.content[ ### .center[When to run `git commit`?] Commit early & often. The more you commit, the easier it is to track growth/history. ### .center[How do I view my commits?] .center[With [`git log`](https://git-scm.com/docs/git-log).] ### .center[Can I make my commits pretty?] Yes! `git log --graph --decorate --all` Example: <br> .center[<img src="assets/img/git-log.png" style="max-width:100%">] ]] --- class: m1 split-two .column[.content[ # [`git pull`](https://git-scm.com/docs/git-pull) Adds changes from remote repo into local repo. <br> Under the hood, this runs [`git fetch`](https://git-scm.com/docs/git-fetch) then [`git merge`](https://git-scm.com/docs/git-merge) <br> .center[<img src="assets/img/git-pull.png" style="max-width:77.5%">] ]] .column.split-20[.row[.vmiddle[ ### .center[When to run `git pull`?] Run when you want other peoples' changes. ]].row.split-50[.row[.vmiddle[ ### .center[**WHEN** Though?] To keep (not ***lose***) your working directory changes, `commit` all changes 1st. `Pull` ***after***. <br> However, committing **MIGHT** lead to [merge conflicts](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merge_conflicts), so `git pull` wisely. <br> [`git stash`](https://git-scm.com/docs/git-stash) can be used as a work around. ]].row[ ### .center[A good workflow/convention] .center[![](assets/img/git-workflow-scaled.svg)] ]]] --- class: m1 split-two .column[.content[ # [`git push`](https://git-scm.com/docs/git-push) Updates remote repository branches/tags (refs). <br> Pushing a brand new Git repo: <br> .center[<img src="assets/img/git-push-new.png" style="max-width:95%">] ]] .column.split-20[.row[.vmiddle[ ### .center[When to run `git push`?] Run when you want ***others*** to access your work. ]].row.split-30[.row[.vtop-0[ ### .center[**WHEN** Though?] basic scenarios: 1. Brand new remote repo (left) 2. After cloning (below left) 3. After pulling (below right) ]].row.split-two[ .column[ ![](assets/img/git-push-clone.png)] .column[ ![](assets/img/git-push-pull.png) <img src="assets/img/git-push-pull-log.png" style="max-width:45%">] ]]] --- class: middle center # .x300.advent-pro[Undoing Things] --- class: m1 split-two .column[.content[ # [`git reset`](https://git-scm.com/docs/git-reset) Resets HEAD to the state that you tell it to. <br> .center[<img src="assets/img/git-reset-1.png" style="">] .center[<img src="assets/img/git-reset-2.png" style="">] ]] .column.split-20[.row[.vmiddle[ ### .center[When to run `git reset`?] Run when you have made personal oopsies. ]].row[ ### .center[**WHEN** Though?] - When you want to undo the latest commit. - `git reset --soft HEAD~1` (previous commit) (top left) - When you want to throw out additions to the index, e.g. you ran `git add .` by accident - `git reset` (runs `git reset --mixed` as default) (mid top left) - When you want to discard all modifications in working directory/tree - `git reset --hard` or `git reset --hard HEAD` (adds `HEAD` by default) (mid bottom left) - When you want to throw out commits (**forever**) - `git reset --hard HEAD~1` (previous commit) (bottom left) .x75[What is this `HEAD~1` notation? - `~n` means `\(n^{th}\)` generation of the named commit. So `HEAD~1` refers to the commit before the latest (e.g. 1 before HEAD). - You can Boggle your brains at [`man gitrevisions`](https://git-scm.com/docs/gitrevisions) or <br> [Git Tools - Revision Selection](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection) ]]] --- class: m1 split-two .column[.content[ # [`git revert`](https://git-scm.com/docs/git-revert) Undos commits & records new ones with the "fix"! <br> .center[<img src="assets/img/git-revert.png" style="">] ]] .column.split-20[.row[.vmiddle[ ### .center[When to run `git revert`?] Run when you need to undo a commit. ]].row[ ### .center[**WHEN** Though?] When you find a bug or small issue introduced by a commit. <br><br> **Note**: this can easily lead to [merge conflicts](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merge_conflicts). ]] --- class: m1 split-two .column[.content[ # [`git rm`](https://git-scm.com/docs/git-rm) Removes files from the Working Tree & the Index. <br> .center[<img src="assets/img/git-rm.png" style="">] ]] .column.split-20[.row[.vbottom-0[ ### .center[When to run `git rm`?] Run when you've tracked files with Git that you didn't want to (yet). ]].row[ ### .center[**WHEN** Though?] You ran a `git add` on your really large data file (oops). <br><br> **Note**: not a silver bullet, git still has your data stored in its history *if* you already committed it. In which case, a `git reset` or creating a new repo may be desired. ]] --- class: middle center # .x300.advent-pro[Development Operations] --- class: m1 split-two .column[.content[ # <center>"Branching"</center> The concept of diverging from the main line of development. <br><br> "Branch"es can be used to develop features isolated from one another. <br><br> .center[![Branches from Git the Simple Guide](assets/img/branches.png)] - See [Git Branching in a Nutshell](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) - See [branching](http://rogerdudler.github.io/git-guide/#branching) in [git the simple guide](http://rogerdudler.github.io/git-guide/) Merging - [Atlassian on Git Merge](https://www.atlassian.com/git/tutorials/using-branches/git-merge) ]] .column[.content[ ### .center[3 new commands] [`git checkout`](https://git-scm.com/docs/git-checkout), [`git branch`](https://git-scm.com/docs/git-branch), [`git merge`](https://git-scm.com/docs/git-merge) ### .center[Example] .center[<img style="max-width:60%" src="assets/img/branching.png">] ]] --- class: m1 split-two .column[.content[ # [`git checkout`](https://git-scm.com/docs/git-checkout) Lets you switch between differing files, commits, and branches (more than creating/switching to new branches with the `-b` flag). <br> .center[<img src="assets/img/git-checkout.png" style="max-width:83%">] ]] .column.split-20[.row[.vbottom-0[ ### .center[When to run `git checkout`?] Run when creating a new feature branch, or when you need to access/use old files & commits. ]].row[ ### .center[**WHEN** Though?] Too many scenarios. See [`git checkout --help`](https://git-scm.com/docs/git-checkout) & the ["EXAMPLES"](https://git-scm.com/docs/git-checkout#_examples) section. Here are a few: ```bash # create / switch to new branch git checkout -b feature-branch # checkout old file(s) # [<tree-ish>] is a revision selection / commit # <paths> are files / file patterns git checkout [<tree-ish>] <paths> # checkout previous commits # grab <commit> from `git log` & use >= 7 characters git checkout <commit> ``` ]] --- class: m1 split-two nomargin-ul .column[.content[ # <center>Releases</center> [Releases](https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/managing-releases-in-a-repository) are versions of packaged software. ### Anatomy Produced from [Git "tags"](https://git-scm.com/book/en/v2/Git-Basics-Tagging), contain release notes, and include binary installation assets for supported OS's. ### Release Cycle Involves "building" assets, performed via CI/CD pipelines: - e.g. [GitLab CI/CD](https://docs.gitlab.com/ee/ci/), [GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions), [Jenkins](https://jenkins.io), [AWS Codepipeline](https://aws.amazon.com/codepipeline/), [Travis CI](https://travis-ci.org/), 2-many-services, etc. ### R Package example - [R Markdown](https://github.com/rstudio/rmarkdown) - [Releases](https://github.com/rstudio/rmarkdown/releases) - [GitHub Workflows](https://github.com/rstudio/rmarkdown/tree/master/.github/workflows) - [GitHub Actions for the R Language](https://github.com/r-lib/actions) ]] .column[.content[ ### .center[1 new command & 99 tools ...] [`git tag`](https://git-scm.com/docs/git-tag) ### .center[Example (1 tool)] .center[<img style="max-width: 91%" src="assets/img/releases.png">] ]] --- class: m1 split-two .column[.content[ # [`git tag`](https://git-scm.com/docs/git-tag) Creates, lists, and deletes Git tags. <br> .center[<img src="assets/img/git-tag.png" style="max-width:80%">] ]] .column.split-20[.row[.vbottom-0[ ### .center[When to run `git tag`?] Run when you are ready to create a newly versioned release of your software. ]].row[ ### .center[**WHEN** Though?] Examples for M&A's usages: - When a new version of an R package is created - Updates to our web apps - After writing features to an ETL process - Before an EC2 instance is ready to be snapshotted - If shell code is used & formed into a repo to configure instance - i.e. using a configuration management tool like [Puppet](https://puppet.com/products/puppet-enterprise)/[Ansible](https://www.ansible.com) - delivering on compliant software through the RMF cycle using tools like [Chef](https://www.chef.io/products/chef-compliance) ]] --- class: middle center # .x500.advent-pro[LARGE] .x200.advent-pro-ital[Files] --- class: m1 split-10 .row[ # .center[Dealing with Large Files] ] .row.split-two[ .column[.content[ ### .center[Use AWS S3 *most* of the time] .center[<img src="assets/img/s3-large-files.png" style="max-width:89%">] ]] .column[.content[ ### .center[Use Git LFS *some* of the time] .x75[ [Git Large File Storage (LFS)](https://git-lfs.github.com/), is an extension to Git that replaces large files with text pointers inside of Git, while storing file contents on remote servers (like GitLab, GitHub, etc.) <br><br> [Quotas](https://forum.gitlab.com/t/max-size-per-repo/17403) or [billing accounts](https://docs.github.com/en/free-pro-team@latest/github/managing-large-files/about-storage-and-bandwidth-usage) can get involved (depending on service). You also may deal with [file locking](https://github.com/git-lfs/git-lfs/wiki/File-Locking) (helps prevent merge conflicts). .center[<img src="assets/img/git-lfs.png" style="">] Learn to [install/configure the AWS CLI](https://esgovcloud.com/mAndA/dev-docs/wiki/AWS-CLI) in our [dev-docs](https://esgovcloud.com/mAndA/dev-docs/wiki) ]]] ] --- class: m1 split-10 .row[ # .center[Git Aliases & Extras] ] .row.split-two[ .column.split-30.with-border[ .row[.content[ ### .center[Git Aliases] A popular "framework" for Zsh, [Oh My Zsh](https://github.com/ohmyzsh/ohmyzsh), contains built in [plugins](https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins) for shell utilities. <br><br> The [Git plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/git) provides **many** useful aliases. ]] .row[.content[ A shell [`alias`](https://www.gnu.org/software/bash/manual/html_node/Aliases.html) is a string/shortcut to a command within a shell session. <br><br> Shell aliases are set via:<br>`alias <alias-name>="<alias command>"` <br> Are unset via:<br>`unalias <alias-name>` <br> Are viewed simply via:<br>`alias` or `alias <alias-name>` <br><br> The [Zsh](http://zsh.sourceforge.net) ("Z Shell"), is a shell based on *[bash](https://www.gnu.org/software/bash/manual/bash.html#Introduction), ksh, and tcsh*. It is the [default Terminal shell on macOS >= 10.15](https://support.apple.com/en-us/HT208050). ]]] .column[.content[ ### .center[Git Extras] You can chain together Git tasks into functions, or even new `git` commands, like the [Git Extras](https://github.com/tj/git-extras) project. You can checkout the [commands here](https://github.com/tj/git-extras/blob/master/Commands.md). ### .center[GitHub/GitLab CLIs] CLI tools for common GitHub / GitLab tasks (e.g. pull/merge requests) are in development. - GitHub CLI: [`gh`](https://cli.github.com) - GitLab CLI: [`glab`](https://glab.readthedocs.io) Can both be easily configured for Enterprise Servers - [GitHub CLI - Enterprise Server](https://cli.github.com/manual/#github-enterprise-server) - [GitLab CLI - Enterprise Server](https://github.com/profclems/glab#configuration) ]] ] --- class: middle center # .x300.advent-pro[R / Git Project Template] --- class: m1 split-two .column[.content[ ]] .column[.content[ ]] --- class: center middle # .x300.advent-pro[Git or Done] --- name: resources class: nomargin-ul nomargin-h2 nomargin-h3 nomargin-h4 nopadding-h2 split-7 .row[ ## <center>Presentation Resources</center> ] .row[ .split-three[ .column.center[ ### [Setup](#3) #### [Friends of Git](#4) Windows - [Git for Windows](https://gitforwindows.org) - [Terminal Emulator](https://esgovcloud.com/mAndA/savi/blob/master/CONTRIBUTING.md#windows-10) - [chocolatey](https://chocolatey.org), [scoop](https://scoop.sh), [winget](https://github.com/microsoft/winget-cli) macOS - [Homebrew](https://brew.sh) - [iTerm2](https://www.iterm2.com/index.html) #### [SSH Keys](#5) - [Connecting to GitHub with SSH](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) - [GitLab and SSH keys](https://docs.gitlab.com/ee/ssh/README.html) #### [Getting Started](#9) - [Demo Repo to Clone]() #### [R Project + RStudio + Git](#10) - [Using Projects in R / RStudio](https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects) #### [CLI, Aliases, & Extras](#29) - [Oh My Zsh Git Plugin Aliases](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/git) - [Git Extras](https://github.com/tj/git-extras) - [GitHub CLI](https://cli.github.com) - [GitLab CLI](https://glab.readthedocs.io) ] .column.center[ ### Concepts - [gitignore](https://git-scm.com/docs/gitignore) - [merge conflicts](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merge_conflicts) #### [3 Trees of Git](#12) - [Git Reset / 3 Trees](https://www.atlassian.com/git/tutorials/undoing-changes/git-reset) #### [Revision Selection](#19) - [man gitrevisions](https://git-scm.com/docs/gitrevisions) - [Git Tools - Revision Selection](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection) #### [Branching](#23) - [Git Branching in a Nutshell](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) #### [Releases](#25) - [Git Basics Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging) - [GitHub - Managing Releases](https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/managing-releases-in-a-repository) - [GitLab](https://docs.gitlab.com/ee/user/project/releases/index.html) CI/CD Pipelines - [GitLab CI/CD](https://docs.gitlab.com/ee/ci/), [GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions), [Jenkins](https://jenkins.io), [AWS Codepipeline](https://aws.amazon.com/codepipeline/), [Travis CI](https://travis-ci.org/) #### [Large Files](#28) - [AWS CLI Install / Config]() - [Git Large File Storage](https://git-lfs.github.com/) ### Guides / Resources - [Git the Simple Guide](http://rogerdudler.github.io/git-guide/) - [Dev Docs]() ] .column.center[ ### Git Commands - [git status](https://git-scm.com/docs/git-status) - [git clone](https://git-scm.com/docs/git-clone) - [git init](https://git-scm.com/docs/git-init) - [git remote](https://git-scm.com/docs/git-remote) - [git add](https://git-scm.com/docs/git-add) - [git commit](https://git-scm.com/docs/git-commit) - [git log](https://git-scm.com/docs/git-log) - [git pull](https://git-scm.com/docs/git-pull) - [git push](https://git-scm.com/docs/git-push) - [git reset](https://git-scm.com/docs/git-reset) - [git revert](https://git-scm.com/docs/git-revert) - [git rm](https://git-scm.com/docs/git-rm) - [git branch](https://git-scm.com/docs/git-branch) - [git checkout](https://git-scm.com/docs/git-checkout) - [git merge](https://git-scm.com/docs/git-merge) - [git tag](https://git-scm.com/docs/git-tag) - [git lfs](https://github.com/git-lfs/git-lfs/tree/master/docs) ] ]]