command | function |
---|---|
git init | initiate git |
git add folder/ | stage/add a folder and its contents |
git add filename.ext | stage/add a file |
git add -u | stage all modified but unstaged files |
git commit -m "message" | commit the changes to local git |
git push | push current state of local git to remote repo |
git remote -v | print remote fetch/pull URLs |
git remote set-url origin git@github.com:username/repo.git | change remote repository; e.g., if you changed the GH repo name (GH repo > Settings > rename) |
Git and GitHub
How to follow
All code should be added into the Terminal tab (in the Console pane in RStudio). Alternatively, you don’t need to use the Terminal at all, as RStudio adds a Git tab to the Environment pane. For a much more in-depth (and better) guide, follow the amazing Happy git with R book by Jenny Bryan.
I use git right in the Terminal window in RStudio. To get to the Terminal window, look where you usually see the output from your code (probably the bottom left window, ‘Console’). You should see a tab ‘Terminal’. This is where you want to go. Now you can start setting up git using the following commands.
For the purposes of this guideline, I’ll be using my ‘dissertation’ folder as an example, which contains all the files and folders necessary to knit my dissertation with oxforddown.
All code chunks below contain copy-and-pasted commands and output from my Terminal, so you can see exactly how it should look.
Summary of commands
command | function |
---|---|
git remote -v | print remote fetch/pull URLs |
git reset | unstage all |
git checkout | remove unstaged changes |
git log --oneline | List the unique hash for each commit in a repo |
git revert 2f5451f --no-edit | undo a commit with the hash 2f5451f (replace this with the relevant commit hash) |
git reset --soft HEAD~ | undo last commit (that was not pushed) |
git reset --soft HEAD~2 | undo last 2 commits (that were not pushed) |
git push -f origin main | overwrite remote repo with local repo code (force changes, even when discrepancies are present; DO NOT do this on a collaboration repo unless you're sure nobody else has made changes to the remote branch you're pushing to! |
Local repositories
Local repositories are those that are stored on your machine (computer). They’re great for tracking changes you make along the way, but if your machine is lost/stolen/damaged, your local repository goes along with it. It’s a great idea to get familiar with git in local contexts, but remote repositories are the real life savers (next section).
Setting up git
Install git
You’ll first need to already have git installed locally. To see how to do that, go here: https://git-scm.com/download/. If you don’t know whether you already have git installed, use the code in the section below (check git version).
Check git version
git version
= check your version of git
-MacBook-3:dissertation danielapalleschi$ git version # this is where i typed 'git version'
(base) administrators2.32.1 (Apple Git-133) # and this was the output git version
git config --list
= check your configurations
git config --global user.name "your-name"
= globally set your name git config --global user.email "your-email"
= globally set your email pwd
= print working directory cd
= change directory
pwd/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation
cd dissertation# no output
pwd/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation/dissertation
## What the Terminal should look like after you've run all 3 commands
-MacBook-3:Dissertation danielapalleschi$ pwd # command 1
(base) administrators/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation
-MacBook-3:Dissertation danielapalleschi$ cd dissertation # command 2
(base) administrators-MacBook-3:dissertation danielapalleschi$ pwd # command 3
(base) administrators/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation/dissertation
-MacBook-3:dissertation danielapalleschi$ (base) administrators
Adding git repo
git status
= check status of git repogit init
= put a git repo in to track changesgit add
= add files/folders to track
git status
-MacBook-3:dissertation danielapalleschi$ git status # command
(base) administrators
On branch master
No commits yet
:
Untracked files"git add <file>..." to include in what will be committed)
(use /../../.DS_Store
../../../.gitignore
../../
../../../Participant Money/
../../../R template scripts/
../../../Stats/
../../../Talks/
../../../presupposition.docx
..
present (use "git add" to track)
nothing added to commit but untracked files -MacBook-3:dissertation danielapalleschi$ (base) administrators
git init
-MacBook-3:dissertation danielapalleschi$ git init
(base) administrators: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name> hint
Hmm, GitHub recently changed ‘master’ to ‘main’. Let’s do the same, first globally but also locally:
-MacBook-3:dissertation danielapalleschi$ git config --global init.defaultBranch main
(base) administrators-MacBook-3:dissertation danielapalleschi$ git branch -m main (base) administrators
Now let’s check the status of our repo:
-MacBook-3:dissertation danielapalleschi$ git status
(base) administrators# So changing 'master' to 'main' worked :)
On branch main
No commits yet
: # list of all the files to add...
Untracked files"git add <file>..." to include in what will be committed)
(use /
.github
.gitignore00-introduction.Rmd
00-introduction.tex
01-how-to-use.tex
01-processing.Rmd
01-processing.pdf
01-processing.tex
02-tense-lifetime.Rmd
02-tense-lifetime.pdf
02-tense-lifetime.tex
03-exp123.Rmd
03-exp123.log
03-exp123.maf
03-exp123.mtc
03-exp123.mtc0
03-exp123.pdf
03-exp123.tex
03-rmd-basics-cites-and-refs.tex
04-exp345.pdf
04-exp345.tex
04a-exp4-context.Rmd
04b-exp5-world.Rmd
04c-exp6-ps-replication.Rmd
05-dfg.Rmd
05-dfg.pdf
05-dfg.tex
06-conclusion.Rmd
LICENSE
README.md
_bookdown.yml/
bibliography/
data/
docs/
figures-and-back-matter/
front
index.Rmd/
scripts_and_filters/
templates
present (use "git add" to track) nothing added to commit but untracked files
For now, I want to commit the chapters I’m working on. So I’ll add them.
-MacBook-3:dissertation danielapalleschi$ git add 03-exp123.Rmd
(base) administrators-MacBook-3:dissertation danielapalleschi$ git add 04a-exp4-context.Rmd
(base) administrators-MacBook-3:dissertation danielapalleschi$ git add 04b-exp5-world.Rmd
(base) administrators-MacBook-3:dissertation danielapalleschi$ git add 04c-exp6-ps-replication.Rmd
(base) administrators-MacBook-3:dissertation danielapalleschi$ git add 05-dfg.Rmd
(base) administrators-MacBook-3:dissertation danielapalleschi$ git add 01-processing.Rmd
(base) administrators-MacBook-3:dissertation danielapalleschi$ git add 02-tense-lifetime.Rmd
(base) administrators) administrators-MacBook-3:dissertation danielapalleschi$ git status # now check the status
base
On branch main
No commits yet
:
Changes to be committed"git rm --cached <file>..." to unstage)
(use : 01-processing.Rmd
new file: 02-tense-lifetime.Rmd
new file: 03-exp123.Rmd
new file: 04a-exp4-context.Rmd
new file: 04b-exp5-world.Rmd
new file: 04c-exp6-ps-replication.Rmd
new file: 05-dfg.Rmd
new file
:
Untracked files"git add <file>..." to include in what will be committed)
(use /
.github
.gitignore00-introduction.Rmd
00-introduction.tex
01-how-to-use.tex
01-processing.pdf
01-processing.tex
02-tense-lifetime.pdf
02-tense-lifetime.tex
03-exp123.log
03-exp123.maf
03-exp123.mtc
03-exp123.mtc0
03-exp123.pdf
03-exp123.tex
03-rmd-basics-cites-and-refs.tex
04-exp345.pdf
04-exp345.tex
05-dfg.pdf
05-dfg.tex
06-conclusion.Rmd
LICENSE
README.md
_bookdown.yml/
bibliography/
data/
docs/
figures-and-back-matter/
front
index.Rmd/
scripts_and_filters/ templates
Tracking changes
git diff
= Show unstaged changes between your index and working directorygit commit -m "<message>"
= commit the changes, with the following messagegit log
= Display the entire commit history using the default format
First, I made some changes: Rename ‘Interpretation’ to ‘Discussion’ and remove the ‘save.image…’ code chunk from the end of 04a-exp4-context.Rmd
.
-MacBook-3:dissertation danielapalleschi$ git diff # command
(base) administrators--git a/04a-exp4-context.Rmd b/04a-exp4-context.Rmd
diff 100644
index ab6a2bb..a883ab4 --- a/04a-exp4-context.Rmd
+++ b/04a-exp4-context.Rmd
Commit this change
-MacBook-3:dissertation danielapalleschi$ git commit -m "Update Context Exp headers"
(base) administratorsmain (root-commit) dabe29e] Update Context Exp headers
[7 files changed, 10363 insertions(+)
100644 01-processing.Rmd
create mode 100644 02-tense-lifetime.Rmd
create mode 100644 03-exp123.Rmd
create mode 100644 04a-exp4-context.Rmd
create mode 100644 04b-exp5-world.Rmd
create mode 100644 04c-exp6-ps-replication.Rmd
create mode 100644 05-dfg.Rmd create mode
Check the log
-MacBook-3:dissertation danielapalleschi$ git log
(base) administratorsdabe29e9d594c578971e07e09e1b57c89572b582 (HEAD -> main)
commit : Daniela Palleschi <palleschi.daniela@gmail.com>
Author: Fri Jul 1 14:16:26 2022 +0200
Date
Update Context Exp headers
But this updated ‘main’. Let’s try to only update the relevant file.
-MacBook-3:dissertation danielapalleschi$ git commit 04a-exp4-context.Rmd -m "Updated Context Exp headers"
(base) administrators85468f5] Updated Context Exp headers
[main 1 file changed, 1 insertion(+), 4 deletions(-)
Good. Now check log.
-MacBook-3:dissertation danielapalleschi$ git log
(base) administrators85468f585608b5c8d94d4b9af40898c5a961110c (HEAD -> main)
commit : Daniela Palleschi <palleschi.daniela@gmail.com>
Author: Fri Jul 1 14:18:08 2022 +0200
Date
Updated Context Exp headers
commit dabe29e9d594c578971e07e09e1b57c89572b582: Daniela Palleschi <palleschi.daniela@gmail.com>
Author: Fri Jul 1 14:16:26 2022 +0200
Date
Update Context Exp headers
Stage all modified files.
-u git add
Remote repositories with RStudio
Taken for granted
From this point on, I take for granted:
- git is already installed on my machine
- I have a GitHub account
- already got RStudio set up with an SSH key (Tools > Global Options > Git).
- with an SSH key, I should always make sure to copy the SSH url and not the HTTPS (which would require a Personal Access Token (PAT))!
If these steps haven’t already been taken, check out the first chapter from https://happygitwithr.com/index.html
If you’ve done all that, follow along from here (following https://happygitwithr.com/rstudio-git-github.html#rstudio-git-github)
Setting up
Steps:
- Create a repo in GitHub
- make sure to click ‘create README.md’
- Create a new RProject with Version Control
- add the URL from your GitHub repo, press the green ‘Clone <>’ button
- copy the url, but make sure you choose the relevant format! SSH if you’ve got an SSH key set up, or HTTPS if you’re using a personal access token (PAT)
- stage (add), commit, some arbitray changes
- using either the Git tab, or preferably using the Terminal (see below for examples)
# add a line to your README
"This is a line from RStudio" >> README.md
echo # check the status
git status# stage the change
git add README.md# commit the change and add a message
-m "first commit from RStudio"
git commit # push the change to GitHub
git push# now, go refresh your GH repo and see the change
Other commands
- check working directory
# print working directory; should be to your project folder
pwd
- change working directory
# change directory, in case not your project folder
cd
- list all files in working directory
# list all files in WD
ls
- list all files in working directory, including ignored ones
# list all files including ignored ones
-a ls
- check git status (what’s been staged, what not)
# check status
status
- add files to .gitignore (so they won’t be monitored)
# add file/folder to gitignore (so git will ignore it)
/ >> .gitignore echo Slides
- check remote repo URL
# check what your remote repo URL is
-v git remote
Keeping up changes
If you’ve already started working on the project locally, you can just drag-and-drop your files/folders into the Terminal
# stage change (need to do it every time)
add filename.Rmd# commit these changes to git
-m "message about commit"
commit # check the status
status# push these changes to remote repo
push
Alternatively, you don’t need to use the Terminal at all (but it’s good practice to know how to in order to understand the logic/workflow). In the ‘Environment’ pane, you should see a ‘Git’ tab (if git is indeed set up). You can tick the ‘Staged’ button for all files whose changes you want to commit. Then click ‘commit’. A message window will come up, add your message and click ‘Commit’. Then, Click ‘Push’ to push to GH.
Branches and merging
Create a new branch
To create a new branch in your local repo:
git checkout -b my_branch
And push this branch to a remote repository:
git push -u origin my_branch
Here I created a new branch:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git checkout -b new_branch Switched to a new branch 'new_branch'
And here I pushed it to my remote repo:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git push -u origin new_branch
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for new_branch, visit:
remote: https://scm.cms.hu-berlin.de/pallescd/lifetime_paper1_exp123/-/merge_requests/new?merge_request%5Bsource_branch%5D=new_branch
remote:
To scm.cms.hu-berlin.de:pallescd/lifetime_paper1_exp123.git * [new branch] new_branch -> new_branch
branch 'new_branch' set up to track 'origin/new_branch'.
Deleting a branch
First make sure you are not currently in the branch! E.g., git checkout main
to switch to main.
To delete a branch locally:
git branch -d my_local_branch
And to delete it remotely:
git push origin --delete my_remote_branch
Here I deleted the new branch locally:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git branch -d new_branch Deleted branch new_branch (was 1bf9cc6).
And remotely:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git push origin --delete new_branch
To scm.cms.hu-berlin.de:pallescd/lifetime_paper1_exp123.git - [deleted] new_branch
Switching and checking branches
If you want to see which branches you have (your current branch will be highlighted and have an asterisk):
git branch
Or to see only the name of your current branch:
git branch --show-current
To switch between branches:
git checkout my_branch
Here is the history of me switching between and checking my branches, where I’m working on a branch called revisions1
:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git branch
main* revisions1
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git branch --show-current
revisions1
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git branch* main
revisions1
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git checkout revisions1
Switched to branch 'revisions1' Your branch is up to date with 'origin/revisions1'.
Merge branches
You want to be careful here. First, make sure both your branch and the main/master (trunk) are up-to-date with your remote repo (or that your remote repo is up-to-date with your local changes).
git checkout my_branch
git pull
git checkout main git pull
Then to merge the branches, but not commit the merge in case of conflicts:
git merge --no-ff --no-commit my_branch
If there are no conflicts, then commit and push
-m "merging my_branch with main"
git commit git push
Here is the history from when I recently did this:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git checkout revisions1
Switched to branch 'revisions1'
Your branch is up to date with 'origin/revisions1'.
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git pull
Already up to date.
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git pull
Already up to date.
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git merge --no-ff --no-commit revisions1
Automatic merge went well; stopped before committing as requested
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git status
On branch main
Your branch is up to date with 'origin/main'.
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
[...]
And commited the merge:
-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git commit -m "merge revisions1: formulae tables in Appendices"
Administrators39f1720] merge revisions1: formulae tables in Appendices [main
And push the merge to GitLab (which I use for manuscripts, instead of GitHub):
-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git push
Administrators: 1, done.
Enumerating objects: 100% (1/1), done.
Counting objects: 100% (1/1), 242 bytes | 242.00 KiB/s, done.
Writing objects1 (delta 0), reused 0 (delta 0), pack-reused 0
Total -berlin.de:pallescd/lifetime_paper1_exp123.git
To scm.cms.hu39f1720 main -> main b9c3533..
Updating development branch
Sometimes the main branch will have changes not yet available in the development branch. This can happen e.g., when you forget to switch from the main to development branch before making changes (as I often do when working in a private repo), or if a collaborator has pushed and merged some changes from their development branch. Ignoring the fact that this might introduce conflicts with your development branch and assuming your branch was otherwise previously up-to-date with the main branch, here is what you would do:
git checkout my_branch
git fetch origin git merge origin/main
Here is some recent output from when I did this and had created a new folder in main which was not yet avaialble in my development branch ‘revisions1’:
Switching to my dev branch:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git checkout revisions1
Switched to branch 'revisions1' Your branch is up to date with 'origin/revisions1'.
Fetching the changes from main:
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git fetch origin
Merging these changes to my dev branch (had a very long output because it was a whole morning’s worth of changes):
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git merge origin/main
Updating 2a9159b..94439d8
Fast-forward[...]
Git for collaboration
If you’ve got a git repo set up and want to add a member:
In a GitLab repo: + Project Information > Members > Invite members
New laptop or expired SSH key
If you have everything backed up, and are running your same projects etc. on a new machine (or if your SSH key simply expired), then you just need to generate a new SSH key in RStudio. Then, go to your GitHub or GitLab Settings, go to the tab for SSH keys, and add a the new SSH key. In other words, follow these steps:
- Create SSH key (in RStudio) and save to clipboard (e.g., CTRL+C)
- RStudio > Tools > Global Options > Git/SVN > SSH key > Create SSH Key… > OK > View public key; copy key
- Add SSH key to you GitHub and/or GitLab account
- GitHub > Settings > SSH and GPG keys > New SSH key; paste key
- GitLab > Preferences > SSH keys > Key / title etc.; paste key
Expired Personal Access Token
I was having trouble installing the developer package rbbt
in a new RProject that had renv
installed). The error I was receiving was:
Using GitHub PAT from the git credential store.
Error: Failed to install 'unknown package' from GitHub:
HTTP error 401. Bad credentials
So it was a GitHub related issue. This was after recently receiving an e-mail that my Personal Access Token had expired (it was actually expired for about 3 months already). I had ignored this e-mail because I forgot why I even need a PAT, and so I went on with my life.
The solution: I needed to generate a new PAT, which I did by following a link provided in that 3-month old GitHub email (GitHub > Settings > Developer Settings > Personal access tokens > Tokens (classic) > Generate new token). I then copied and saved the PAT in a file where I keep track of my PATs, and then in the relevant RProject ran the following:
- Print the current PAT to check if there is one, and if it’s the expired one:
Sys.getenv("GITHUB_PAT")
- Set the new PAT (here replaced with
mypat
)
Sys.setenv(GITHUB_PAT = "mypat")
- Print the PAT to check that it’s the new one
Sys.getenv("GITHUB_PAT")
- Finally, install the package I was trying to install
::install_github("paleolimbot/rbbt") devtools