└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Git/GitHub Cheat Sheet 2 | 3 | I am compiling here a useful list of commands and procedures for working with git and GitHub, particularly from RStudio using the [usethis](https://usethis.r-lib.org/) package (which must be installed first), but also directly from the command line. I preface all command line entries with `$`. 4 | 5 | Feel free to for this for your own use. 6 | 7 | **Table of Contents** 8 | 9 | - [Git set up](#git-set-up) 10 | - [Initialize a git repo and sync it with GitHub](#initialize-a-git-repo-and-sync-it-with-github) 11 | - [Clone a GitHub repository locally](#clone-a-github-repository-locally) 12 | - [Basic git workflow](#basic-git-workflow) 13 | - [Branching and merging](#branching-and-merging) 14 | - [Undoing stuff in git](#undoing-stuff-in-git) 15 | - [The .gitignore file](#the-gitignore-file) 16 | - [Useful links](#useful-links) 17 | 18 | ## Git set up 19 | 20 | To set up your your basic git configuration, you can `use_git_config`. From an R console: 21 | 22 | ```r 23 | usethis::use_git_config(user.name = "Jane Doe", user.email = "jane@example.com") 24 | ``` 25 | 26 | If you prefer to do this from the command line: 27 | 28 | ```bash 29 | $ git config --global user.name "Jane Doe" 30 | $ git config --global user.email jane@example.com 31 | ``` 32 | 33 | Either way, I would also suggest that if you are on a MacOS system, you also set the `core.editor` to "nano" to avoid being stuck in [vim hell](https://qz.com/990214/a-million-people-have-visited-this-web-page-explaining-how-to-close-vim-a-notoriously-difficult-text-editing-program/). 34 | 35 | If using the `usethis` package, I would also recommend running: 36 | 37 | ```r 38 | usethis::git_vaccinate() 39 | ``` 40 | 41 | This will add several items to your global .gitignore file that will be carried over when you initialize new git projects from RStudio. 42 | 43 | You can always check on the current status of your git in R with: 44 | 45 | ```r 46 | usethis::git_sitrep() 47 | ``` 48 | 49 | ### Setting up a GitHub Personal Access Token 50 | 51 | Working with GitHub remotes now requires a personal access token (PAT) rather than just your GitHub password. This will include any push commands. You can create a appropriate on GitHub by going to your global user settings (not repository settings) and then Developer > Personal access token. However, I would recommend that instead you type the following from the R console: 52 | 53 | ```r 54 | usethis::create_github_token() 55 | ``` 56 | 57 | This will take you to the same page on GitHub, but has the advantage that it will already check all the most common scopes that you need to work with GitHub. If you do it manually, you will need to check the appropriate scopes. 58 | 59 | Copy the PAT (you only get once chance!). Once you have your PAT, you can use it when you are prompted for your "password" when running git operations. To avoid this nuisance, you can instead cache your PAT so that it will be run automatically. From the R console: 60 | 61 | ```r 62 | gitcreds::gitcreds_set() 63 | ``` 64 | 65 | Follow the prompts on-screen and paste your PAT when it is asked for. You should now be able to push to your GitHub repositories without authenticating every time. 66 | 67 | ## Initialize a git repo and sync it with GitHub 68 | 69 | I assume you have a local directory with a project that you would like to turn into a git repository synced to GitHub. With the `usethis` package, this process is straightforward. 70 | 71 | Before beginning, make sure that R is in the correct working directory: 72 | 73 | ```r 74 | getwd() 75 | ``` 76 | 77 | The working directory should be the same as the top-level of the directory that you want to make into a git repository. Once you are sure that this is correct, simply type the following into the R console: 78 | 79 | ```r 80 | # Create an R project in the current working directory. Note that this command 81 | # will open up a new RStudio window with your project loaded. 82 | usethis::create_project(".") 83 | 84 | # Initialize the current directory as a git repository. This command will give 85 | # you a couple of prompts. Most importantly, it will ask you if you want to 86 | # make an initial commit of all the files in the directory. Only do this if 87 | # you are sure all the files should be part of your repository. You can always 88 | # make the initial commit manually by choosing specific files later. 89 | usethis::use_git() 90 | 91 | # Create a repository on GitHub and push everything in this repo to that new 92 | # repository. Note that you need to change `private=TRUE` if you want this to 93 | # be a private repository (public by default) 94 | usethis::use_github(private=FALSE) 95 | ``` 96 | 97 | You are now fully set up and should be able to push and pull between the repositories. 98 | 99 | If you prefer to do this from the command line, you will have to create the new repository on GitHub first and copy the https address for that repository (given to you when you set up the repository for the first time). You can then type into the command line (from the right working directory): 100 | 101 | ```bash 102 | $ git init #initialize the repo 103 | $ git add . #stage all files (you can also pick specific ones instead) 104 | $ git commit -m "initial commit" #make the initial commit 105 | $ git remote add origin #add the GitHub remote as origin 106 | $ git branch -M main #change default branch name to main 107 | $ git push -u origin main #push changes to the GitHub repository 108 | ``` 109 | 110 | You can always run `usethis::git_sitrep()` from R to see the status of your current git repository. 111 | 112 | ## Clone a GitHub repository locally 113 | 114 | Instead of turning a local repository into a GitHub repository, you may want to clone an already existing GitHub repository to your local machine. To do this, you will need to copy the https address for the repository (given under the big green "Code" button on the main page of the repository). 115 | 116 | Once you have the https address, you can clone from the R console with: 117 | 118 | ```r 119 | usethis::create_from_github("", destdir="path/to/destination") 120 | ``` 121 | 122 | If you do not set the `destdir`, then the repository will most likely be cloned to your desktop. If you would like to place the repository in the current working directory, then you can use `destdir="."`. 123 | 124 | Note that if you run this from RStudio, this repository will be initialized as an RStudio project as well. You can control this behavior with the argument `rstudio=TRUE/FALSE`. 125 | 126 | You can also clone from the new project wizard in RStudio. Just go to File > New Project. Then select Version Control > Git. From the final wizard, enter the https address of your GitHub repository and the "Create Project" button. 127 | 128 | If you prefer to clone from git itself, then from the command line (in the correct working directory): 129 | 130 | ```bash 131 | $ git clone 132 | ``` 133 | 134 | Note that this will not set up your git repository as an R Project. You can do this manually from the new project wizard by by selecting the "Existing Directory" option. 135 | 136 | 137 | ## Basic git workflow 138 | 139 | The basic git workflow is: 140 | 141 | 1. Pull in changes from the remote. 142 | 2. Do your work. 143 | 3. Commit changes in small logical chunks. 144 | 4. Push changes to the remote. 145 | 146 | In RStudio, you can use the git tab to accomplish all of these tasks. The commit dialog will allow you to make commits and the push and pull buttons will do pushing and pulling. 147 | 148 | Note that the git tab will only show up in an R project. So if you cloned your repository outside of RStudio, you will need to use the new project wizard to make the existing directory an R project (basically adds an *.Rproj text file). Also, if you did not open a specific project through RStudio, you will not see the git tab even if you are in the correct working directory. To open the project, use the project menu in the upper right or just double-click the *.Rproj file in your system's file viewer. 149 | 150 | If you want to use the basic git workflow from the command line, the first command you should know is: 151 | 152 | ```bash 153 | $ git status 154 | ``` 155 | 156 | This will tell you the current status of your git repository and identify files with uncommitted changes and untracked files. 157 | 158 | You can stage and commit files with: 159 | 160 | ```bash 161 | $ git add fileA fileb some_directory/fileC ... 162 | $ git commit -m "write a commit message" 163 | ``` 164 | 165 | To push and pull: 166 | 167 | ```bash 168 | $ git push 169 | $ git pull 170 | ``` 171 | 172 | Assuming youre remote is named `origin` and your branch is the default `main` branch, you can push with: 173 | 174 | ```bash 175 | $ git push origin main 176 | ``` 177 | 178 | Note that since `origin` is already set up as the default upstream repository for `main`, you can probably just type `git push` and `git pull` and be fine when on the `main` branch. 179 | 180 | ### Amending a commit 181 | 182 | Sometimes, you forget to put something into a commit. The most common case is that you had some unsaved changes in a file because you hadn't saved it recently and realize that after doing the commit. If you realize this before making other commits, you can amend your most recent commit to include the changes. 183 | 184 | You generally should only do this if you have not yet pushed to a remote. If you have pushed to a remote, then the commit histories in the two repositories will not be aligned and you will have to deal with some issues when you next try to pull. 185 | 186 | Assuming you have not pushed, then to amend the previous commit, stage the changes you want to add and then type from the command line: 187 | 188 | ```bash 189 | $ git commit --amend -CHEAD 190 | ``` 191 | 192 | This will amend the previous commit to include the newly staged changes. Alternatively, In RStudio, you can use the "Amend previous commit" checkbox below the commit message in the commit dialog. 193 | 194 | ## Branching and merging 195 | 196 | To create a new branch in RStudio, just click the purple branch button in the upper right of the git tab and provide a name. The advantage of this approach is that will create a corresponding branch on the remote reposistory as well. Next to this button, you will see a drop-down menu that shows you all branches on your local and remote repository and allows you to select the current branch. Always make sure you are on the right branch before committing! 197 | 198 | To switch between existing branches from the command line just use `git checkout`: 199 | 200 | ```bash 201 | $ git checkout branch_name 202 | ``` 203 | 204 | You can also use `git branch` to see all existing branches locally. 205 | 206 | To create a new branch from the command line, just use the `git checkout` command with the `-b` argument: 207 | 208 | ```bash 209 | git checkout -b new_branch_name 210 | ``` 211 | 212 | This will not create a corresponding branch on the remote, however. To add this branch to the remote, you must make a commit and then push that to the remote repository (assuming here that it is named "origin") using the `-u` option: 213 | 214 | ```bash 215 | git push -u origin new_branch_name 216 | ``` 217 | 218 | The `-u` option tells git to use this remote repository as the default for all push commands from this branch, so in the future you should be able to just use `git push` to push changes to the remote repository. 219 | 220 | To merge changes from a branch back into the main branch (or any other branch), you must first switch back to the branch you want to merge changes into. Then you can use the `git merge` command with the name of the branch you want to merge: 221 | 222 | ```bash 223 | $ git checkout main 224 | $ git merge new_branch_name 225 | ``` 226 | 227 | This will checkout the main branch and then merge all off the commits from the `new_branch_name` into `main`. 228 | 229 | Although you can merge from the command line, I highly recommend using [GitHub pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests) to handle merging branches back into main in most cases. 230 | 231 | ## Undoing stuff in git 232 | 233 | You made some changes to files and now realize that you don't like those changes. How do you go back? 234 | 235 | ### Situation 1: You did not commit the changes yet 236 | 237 | If you have not yet committed the changes, then you can checkout the file again from the most recent commit. This will wipe all changes to that file since you last committed. To checkout a file called some_script.R from the command line: 238 | 239 | ```bash 240 | $ git checkout -- some_script.R 241 | ``` 242 | 243 | From RStudio, just right click the file in the git tab and choose "Revert...", although this is technically not a revert (see below). 244 | 245 | ### Situation 2: You committed the change but did not yet push it 246 | 247 | If you are in this situation, then you can reset back to a good commit before the bad commit. Under a normal "soft" reset all of the work in commits since the reset will be left as uncommitted changes, so you will not lose other work, but you will have to recommit it. 248 | 249 | As an example, lets say your last good commit before the commit with the work you want to remove is `ce65533`, then: 250 | 251 | ```bash 252 | $ git reset ce65533 253 | ``` 254 | 255 | All of the work since `ce65533` (including the work you want to remove) will then be left as uncommitted changes which you can selectively recommit. 256 | 257 | If you are ok with losing all of the work in commits since commit `ce65533`, then you can do a "hard" reset. This will delete all of the changes in subsequent commits after `ce65533`. Be **very careful** with this option as that work will be gone permanently. If your bad commit is buried pretty deep in your commit history, this is almost certainly not a good option. You might want to instead consider `git revert`, discussed in the next section. 258 | 259 | ```bash 260 | $ git reset --hard ce65533 261 | ``` 262 | 263 | ### Situation 3: You committed the change and pushed it 264 | 265 | In this case, instead of removing the change, we will do a `git revert` which will add a new commit that "inverts" the original commit. This is generally the safest option for undoing things, but also adds another commit. Lets say that the changes you want to revert are in commit `39c398c`. To revert these changes: 266 | 267 | ```bash 268 | $ git revert 39c398c 269 | ``` 270 | 271 | This will add a new commit that basically does the opposite of whatever is done in commit `39c398c`. Keep in mind that given other change to your code since that commit, this inversion might break your code (if for example, other code depends on an object that this commit created). 272 | 273 | 274 | ## The .gitignore file 275 | 276 | The .gitignore file is a text file in you top-level directory that will tell git what files to ignore when indicating what files should be put under version control. This file will be created automatically if you create the repository through RStudio. If you initialize git from the command line, you will have to create it manually. 277 | 278 | If using RStudio, I recommend you run: 279 | 280 | ```r 281 | usethis::git_vaccinate() 282 | ``` 283 | 284 | This will create a global default .gitignore file in your home directory which will be used as the default when you create any new git repository. 285 | 286 | You can use [globbing parameters](https://linux.die.net/man/7/glob) to identify types of files you might want to ignore. Some common cases are: 287 | 288 | ```gitignore 289 | # ignore all files anywhere in your repository that end in .log 290 | *.log 291 | 292 | # ignore all directories anywhere in your repository that are 293 | # named logs 294 | **/logs 295 | 296 | # ignore all files ending in .log except thisone.log 297 | *.log 298 | !thisone.log 299 | 300 | # ignore any filed named debug log anywhere in the logs directory 301 | # including subdirectories of that directories 302 | logs/**/debug.log 303 | ``` 304 | 305 | What should go into your gitignore file? Here are some possibilities: 306 | 307 | * Any system junk files like .DS_Store 308 | * Any files with sensitive/private information 309 | * Any built files that are created by the scripts 310 | 311 | Here is a starter gitignore file for data science: 312 | 313 | ```gitignore 314 | # files added by usethis::git_vaccinate 315 | .httr-oauth 316 | .Rproj.user 317 | .Rhistory 318 | .Rdata 319 | .DS_Store 320 | # built files 321 | *.html 322 | *.pdf 323 | *.log 324 | # Ignore all the junk created by LaTeX 325 | *.aux 326 | *.out 327 | *.bbl 328 | *.ent 329 | ``` 330 | 331 | ### Removing a file from version control 332 | 333 | If a file has already been committed to version control, then ignoring that file or its type will have no affect on that particular file. To get git to stop tracking changes to a file called some_script.R, you must tell git to stop tracking it: 334 | 335 | ```bash 336 | $ git rm --cached some_script.R 337 | ``` 338 | 339 | You can then delete the file locally and commit the deletion and git will no longer track this file. 340 | 341 | ## Useful links 342 | 343 | * [GitHub-flavored markdown cheat sheet](https://gist.github.com/roshith-balendran/d50b32f8f7d900c34a7dc00766bcfb9c) 344 | * [GitHub's git cheat sheet](https://education.github.com/git-cheat-sheet-education.pdf) 345 | * [Happy Git and GitHub for the useR by Jenny Bryan](https://happygitwithr.com/) 346 | * [Why Jenny Bryan will burn down your computer, eg don't use absolute paths](https://www.tidyverse.org/blog/2017/12/workflow-vs-script/) 347 | * [Kieran Healy's The Plain Person’s Guide to Plain Text Social Science](https://kieranhealy.org/publications/plain-person-text/) 348 | * [Code and Data for the Social Sciences, by Matthew Gentzkow and Jesse M. Shapiro](https://web.stanford.edu/~gentzkow/research/CodeAndData.xhtml) 349 | --------------------------------------------------------------------------------