Daniela Palleschi
  • D. Palleschi
  • Source Code
  1. Next level
  2. Git and GitHub
  • Preface
  • Basics
    • Quarto
    • R for Reproducibility
    • UpdateR and (re-)Install Packages
    • Data dictionary
    • Zotero
  • Next level
    • Git and GitHub
    • Docker
    • Quarto and Git Pages
    • Writing
    • Custom ggplot2 themes

On this page

  • Git and GitHub
    • How to follow
    • Summary of commands
    • Local repositories
      • Setting up git
      • Adding git repo
      • Tracking changes
    • Remote repositories with RStudio
      • Taken for granted
      • Setting up
      • Other commands
      • Keeping up changes
    • Branches and merging
      • Create a new branch
      • Deleting a branch
      • Switching and checking branches
      • Merge branches
    • Updating development branch
    • Git for collaboration
    • New laptop or expired SSH key
    • Expired Personal Access Token
  1. Next level
  2. Git and GitHub

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

Table 1: Summary of useful git commands to get started
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)
Table 2: Summary of useful git commands for when things go wrong
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

(base) administrators-MacBook-3:dissertation danielapalleschi$ git version # this is where i typed 'git version'
git version 2.32.1 (Apple Git-133) # and this was the output

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
(base) administrators-MacBook-3:Dissertation danielapalleschi$ pwd # command 1
/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation
(base) administrators-MacBook-3:Dissertation danielapalleschi$ cd dissertation # command 2
(base) administrators-MacBook-3:dissertation danielapalleschi$ pwd # command 3
/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation/dissertation
(base) administrators-MacBook-3:dissertation danielapalleschi$ 

Adding git repo

  • git status = check status of git repo
  • git init = put a git repo in to track changes
  • git add = add files/folders to track

git status

(base) administrators-MacBook-3:dissertation danielapalleschi$ git status # command
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../../.DS_Store
        ../../../.gitignore
        ../../
        ../../../Participant Money/
        ../../../R template scripts/
        ../../../Stats/
        ../../../Talks/
        ../../../presupposition.docx

nothing added to commit but untracked files present (use "git add" to track)
(base) administrators-MacBook-3:dissertation danielapalleschi$ 

git init

(base) administrators-MacBook-3:dissertation danielapalleschi$ git init
hint: 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>

Hmm, GitHub recently changed ‘master’ to ‘main’. Let’s do the same, first globally but also locally:

(base) administrators-MacBook-3:dissertation danielapalleschi$ git config --global init.defaultBranch main
(base) administrators-MacBook-3:dissertation danielapalleschi$ git branch -m main

Now let’s check the status of our repo:

(base) administrators-MacBook-3:dissertation danielapalleschi$ git status
On branch main # So changing 'master' to 'main' worked :)

No commits yet

Untracked files: # list of all the files to add...
  (use "git add <file>..." to include in what will be committed)
        .github/
        .gitignore
        00-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/
        front-and-back-matter/
        index.Rmd
        scripts_and_filters/
        templates/

nothing added to commit but untracked files present (use "git add" to track)

For now, I want to commit the chapters I’m working on. So I’ll add them.

(base) administrators-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-MacBook-3:dissertation danielapalleschi$ git status # now check the status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   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

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .github/
        .gitignore
        00-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/
        front-and-back-matter/
        index.Rmd
        scripts_and_filters/
        templates/

Tracking changes

  • git diff = Show unstaged changes between your index and working directory
  • git commit -m "<message>" = commit the changes, with the following message
  • git 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.

(base) administrators-MacBook-3:dissertation danielapalleschi$ git diff # command
diff --git a/04a-exp4-context.Rmd b/04a-exp4-context.Rmd
index ab6a2bb..a883ab4 100644
--- a/04a-exp4-context.Rmd
+++ b/04a-exp4-context.Rmd

Commit this change

(base) administrators-MacBook-3:dissertation danielapalleschi$ git commit -m "Update Context Exp headers"
[main (root-commit) dabe29e] Update Context Exp headers
 7 files changed, 10363 insertions(+)
 create mode 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

Check the log

(base) administrators-MacBook-3:dissertation danielapalleschi$ git log
commit dabe29e9d594c578971e07e09e1b57c89572b582 (HEAD -> main)
Author: Daniela Palleschi <palleschi.daniela@gmail.com>
Date:   Fri Jul 1 14:16:26 2022 +0200

    Update Context Exp headers

But this updated ‘main’. Let’s try to only update the relevant file.

(base) administrators-MacBook-3:dissertation danielapalleschi$ git commit 04a-exp4-context.Rmd -m "Updated Context Exp headers"
[main 85468f5] Updated Context Exp headers
 1 file changed, 1 insertion(+), 4 deletions(-)

Good. Now check log.

(base) administrators-MacBook-3:dissertation danielapalleschi$ git log
commit 85468f585608b5c8d94d4b9af40898c5a961110c (HEAD -> main)
Author: Daniela Palleschi <palleschi.daniela@gmail.com>
Date:   Fri Jul 1 14:18:08 2022 +0200

    Updated Context Exp headers

commit dabe29e9d594c578971e07e09e1b57c89572b582
Author: Daniela Palleschi <palleschi.daniela@gmail.com>
Date:   Fri Jul 1 14:16:26 2022 +0200

    Update Context Exp headers

Stage all modified files.

git add -u

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:

  1. Create a repo in GitHub
  • make sure to click ‘create README.md’
  1. 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)
  1. 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
echo "This is a line from RStudio" >> README.md
# check the status
git status
# stage the change
git add README.md
# commit the change and add a message
git commit -m "first commit from RStudio"
# 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
ls -a
  • 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)
echo Slides/ >> .gitignore
  • check remote repo URL
# check what your remote repo URL is
git remote -v

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
commit -m "message about 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

git commit -m "merging my_branch with main"
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:

Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git commit -m "merge revisions1: formulae tables in Appendices"
[main 39f1720] merge revisions1: formulae tables in Appendices

And push the merge to GitLab (which I use for manuscripts, instead of GitHub):

Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git push
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 242 bytes | 242.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To scm.cms.hu-berlin.de:pallescd/lifetime_paper1_exp123.git
   b9c3533..39f1720  main -> main

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:

  1. 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
  2. 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:

  1. Print the current PAT to check if there is one, and if it’s the expired one:
Sys.getenv("GITHUB_PAT")
  1. Set the new PAT (here replaced with mypat)
Sys.setenv(GITHUB_PAT = "mypat")
  1. Print the PAT to check that it’s the new one
Sys.getenv("GITHUB_PAT")
  1. Finally, install the package I was trying to install
devtools::install_github("paleolimbot/rbbt")
Source Code
# Git and GitHub {#sec-git}

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE,
                      eval = F)
```

## 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](https://happygitwithr.com/index.html) 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

```{r}
#| echo: false
#| eval: true
pacman::p_load(
  tidyverse,
  knitr,
  kableExtra
)
```

```{r}
#| echo: false
#| eval: true
#| label: tbl-git
#| tbl-cap: "Summary of useful git commands to get started"

dplyr::tribble(
  ~"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)"
) %>% 
  knitr::kable() %>% 
  kableExtra::kable_styling()
```

```{r}
#| echo: false
#| eval: true
#| label: tbl-git-trouble
#| tbl-cap: "Summary of useful git commands for when things go wrong"

dplyr::tribble(
  ~"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!"
) %>% 
  knitr::kable() %>% 
  kableExtra::kable_styling()
```


## 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

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git version # this is where i typed 'git version'
git version 2.32.1 (Apple Git-133) # and this was the output
```

`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

```{r}
pwd
/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation
```

```{r}
cd dissertation
# no output
```

```{r}
pwd
/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation/dissertation
```

```{r}
## What the Terminal should look like after you've run all 3 commands
(base) administrators-MacBook-3:Dissertation danielapalleschi$ pwd # command 1
/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation
(base) administrators-MacBook-3:Dissertation danielapalleschi$ cd dissertation # command 2
(base) administrators-MacBook-3:dissertation danielapalleschi$ pwd # command 3
/Users/danielapalleschi/Documents/PhD/Dissertation Project/Lifetime Project/Dissertation/dissertation
(base) administrators-MacBook-3:dissertation danielapalleschi$ 
```

### Adding git repo

- `git status` = check status of git repo
- `git init` = put a git repo in to track changes
- `git add` = add files/folders to track

#### `git status`

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git status # command
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ../../../.DS_Store
        ../../../.gitignore
        ../../
        ../../../Participant Money/
        ../../../R template scripts/
        ../../../Stats/
        ../../../Talks/
        ../../../presupposition.docx

nothing added to commit but untracked files present (use "git add" to track)
(base) administrators-MacBook-3:dissertation danielapalleschi$ 
```

#### `git init`

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git init
hint: 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>
```

Hmm, GitHub recently changed 'master' to 'main'. Let's do the same, first globally but also locally:

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git config --global init.defaultBranch main
(base) administrators-MacBook-3:dissertation danielapalleschi$ git branch -m main
```

Now let's check the status of our repo:

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git status
On branch main # So changing 'master' to 'main' worked :)

No commits yet

Untracked files: # list of all the files to add...
  (use "git add <file>..." to include in what will be committed)
        .github/
        .gitignore
        00-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/
        front-and-back-matter/
        index.Rmd
        scripts_and_filters/
        templates/

nothing added to commit but untracked files present (use "git add" to track)
```

For now, I want to commit the chapters I'm working on. So I'll add them.

```{r}
(base) administrators-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-MacBook-3:dissertation danielapalleschi$ git status # now check the status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   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

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .github/
        .gitignore
        00-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/
        front-and-back-matter/
        index.Rmd
        scripts_and_filters/
        templates/
```

### Tracking changes

- `git diff` = Show unstaged changes between your index and working directory
- `git commit -m "<message>"` = commit the changes, with the following message
- `git 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`.

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git diff # command
diff --git a/04a-exp4-context.Rmd b/04a-exp4-context.Rmd
index ab6a2bb..a883ab4 100644
--- a/04a-exp4-context.Rmd
+++ b/04a-exp4-context.Rmd
```

Commit this change

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git commit -m "Update Context Exp headers"
[main (root-commit) dabe29e] Update Context Exp headers
 7 files changed, 10363 insertions(+)
 create mode 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
```

Check the log

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git log
commit dabe29e9d594c578971e07e09e1b57c89572b582 (HEAD -> main)
Author: Daniela Palleschi <palleschi.daniela@gmail.com>
Date:   Fri Jul 1 14:16:26 2022 +0200

    Update Context Exp headers
```

But this updated 'main'. Let's try to only update the relevant file.

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git commit 04a-exp4-context.Rmd -m "Updated Context Exp headers"
[main 85468f5] Updated Context Exp headers
 1 file changed, 1 insertion(+), 4 deletions(-)
```

Good. Now check log.

```{r}
(base) administrators-MacBook-3:dissertation danielapalleschi$ git log
commit 85468f585608b5c8d94d4b9af40898c5a961110c (HEAD -> main)
Author: Daniela Palleschi <palleschi.daniela@gmail.com>
Date:   Fri Jul 1 14:18:08 2022 +0200

    Updated Context Exp headers

commit dabe29e9d594c578971e07e09e1b57c89572b582
Author: Daniela Palleschi <palleschi.daniela@gmail.com>
Date:   Fri Jul 1 14:16:26 2022 +0200

    Update Context Exp headers
```

Stage all modified files.

```{r}
git add -u
```

## 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:

1. Create a repo in GitHub
  - make sure to click 'create README.md'
2. 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)
3. stage (add), commit, some arbitray changes
  - using either the Git tab, or preferably using the Terminal (see below for examples)

```{r, eval = F, echo = T}
# add a line to your README
echo "This is a line from RStudio" >> README.md
# check the status
git status
# stage the change
git add README.md
# commit the change and add a message
git commit -m "first commit from RStudio"
# push the change to GitHub
git push
# now, go refresh your GH repo and see the change
```

### Other commands

- check working directory

```{r, eval = F, echo = T}
# print working directory; should be to your project folder
pwd
```

- change working directory

```{r, eval = F, echo = T}
# change directory, in case not your project folder
cd
```

- list all files in working directory

```{r, eval = F, echo = T}
# list all files in WD
ls
```

- list all files in working directory, including ignored ones

```{r, eval = F, echo = T}
# list all files including ignored ones
ls -a
```

- check git status (what's been staged, what not)

```{r, eval = F, echo = T}
# check status
status
```

- add files to .gitignore (so they won't be monitored)

```{r, eval = F, echo = T}
# add file/folder to gitignore (so git will ignore it)
echo Slides/ >> .gitignore
```

- check remote repo URL

```{r, eval = F, echo = T}
# check what your remote repo URL is
git remote -v
```

### 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

```{r, eval = F, echo = T}
# stage change (need to do it every time)
add filename.Rmd
# commit these changes to git
commit -m "message about 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:

```{markdown}
git checkout -b my_branch
```

And push this branch to a remote repository:

```{markdown}
git push -u origin my_branch
```

Here I created a new branch:

```{markdown}
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:

```{markdown}
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:

```{markdown}
git branch -d my_local_branch
```

And to delete it remotely:

```{markdown}
git push origin --delete my_remote_branch
```

Here I deleted the new branch locally:

```{markdown}
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git branch -d new_branch
Deleted branch new_branch (was 1bf9cc6).
```

And remotely:

```{markdown}
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):

```{markdown}
git branch
```

Or to see only the name of your current branch:

```{markdown}
git branch --show-current
```

To switch between branches:

```{markdown}
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`:

```{markdown}
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).

```{markdown}
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:

```{markdown}
git merge --no-ff --no-commit my_branch
```

If there are no conflicts, then commit and push

```{r}
git commit -m "merging my_branch with main"
git push
```

Here is the history from when I recently did this:

```{markdown}
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:

```{r}
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git commit -m "merge revisions1: formulae tables in Appendices"
[main 39f1720] merge revisions1: formulae tables in Appendices
```

And push the merge to GitLab (which I use for manuscripts, instead of GitHub):

```{r}
Administrators-MacBook-Pro:lifetime_paper1_exp123 danielapalleschi$ git push
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 242 bytes | 242.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To scm.cms.hu-berlin.de:pallescd/lifetime_paper1_exp123.git
   b9c3533..39f1720  main -> main
```

## 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:

```{markdown}
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:

```{markdown}
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:

```{markdown}
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):

```{markdown}
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:

1. **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
2. **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:

```{markdown}
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:

1. Print the current PAT to check if there is one, and if it's the expired one:

```{r}
#| eval: false
Sys.getenv("GITHUB_PAT")
```

2. Set the new PAT (here replaced with `mypat`)

```{r}
#| eval: false
Sys.setenv(GITHUB_PAT = "mypat")
```

3. Print the PAT to check that it's the new one

```{r}
#| eval: false
Sys.getenv("GITHUB_PAT")
```

4. Finally, install the package I was trying to install

```{r}
#| eval: false
devtools::install_github("paleolimbot/rbbt")
```