using version control

imagine we need to work on a document together

how should we do that?

key questions

  • which version of the document is the authoritative one?
  • if you and I change the same thing:
    • how will we know we did that?
    • whose edits should win?
03:00

some solutions

dropbox

shared drive

email

google docs

on plain text

beware

agenda

agenda

  • terminology
  • terminalogy
  • workflows: I
  • tools
  • workflows: II
  • unhappy paths

resources

What They Forgot

Happy Git with R

goals

terminology

git

distributed version control system

repository

./
├── ChangeLog
├── config.site
├── configure*
├── configure.ac
├── configure.patch
├── COPYING
├── doc/
├── etc/
├── INSTALL
├── m4/
├── Makeconf.in
├── Makefile.fw
├── Makefile.in
├── po/
├── README
├── share/
├── src/
├── tests/
├── tools/
├── VERSION
└── VERSION-NICK

remote

git vs. github / gitlab / bitbucket

clone / fork

commit

maininitial commitsnapshot onesnapshot two

diff

maininitial commitsnapshot onesnapshot two

terminalogy

words have meaning

terminal
shell
command-line interface (CLI)1

structure

command subcommand --long-argument -s

creating

mkdir <directory-name>
rmdir <directory-name>
touch <file-name.ext>
cp <from-file> <to-file>
mv

rm -rf <directory>

look around

  • create a directory
  • put some files in it
  • delete it
03:00

workflows: I

systems check

git config --global --list
usethis::git_sitrep()

systems check

hidden files:

ls -lha

CMD + SHIFT + .

new project

  • create project (from rstudio, or terminal)
mkdir intro-git
cd intro-git
git init

git status

run often

git status

 git status
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

add some files

touch index.qmd

untracked files

 git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    _quarto.yml
    index.qmd

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

git stage

 git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   _quarto.yml
    new file:   index.qmd

$ git add index.qmd
warning: LF will be replaced by CRLF in index.qmd.
The file will have its original line endings in your working directory

\r

\n

\r\n


dos2unix

new project, who dis

git config --global user.name edavidaja
git config --global user.email david@posit.cor
usethis::git_sitrep()

git commit

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
#
# Initial commit
#
# Changes to be committed:
#       new file:   _quarto.yml
#       new file:   index.qmd
"~/Documents/projects/intro-git/.git/COMMIT_EDITMSG" 12L, 255B

EDITOR

➡️normal mode
I: insert mode, write a message
ESC: return to normal mode
: : command mode
wq: write the file and quit
q!: quit without saving

CTRL|CMD + O to save
CTRL|CMD + X to exit

git commit -m

 git commit -m "initial commit"
[main (root-commit) cab0112] initial commit
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 _quarto.yml
 create mode 100644 index.qmd

git status

 git status
On branch main
nothing to commit, working tree clean

repeat

with rstudio, vscode

git log

 git log
commit 3efdc26af7bf6ea223bfa61c6cb4507de632690e (HEAD -> main)
Author: edavidaja <edavidaja@hey.com>
Date:   Thu Jul 20 15:03:03 2023 -0400

    added vs code workspace

commit 0d98a3c9cf2a351da39b26adbfad442c834ff8d4
Author: edavidaja <edavidaja@hey.com>
Date:   Thu Jul 20 14:55:34 2023 -0400

    added rstudio project files

commit cab0112f6f96bdd82a46e622d8fccd445fc38d17
Author: edavidaja <edavidaja@hey.com>
Date:   Thu Jul 20 14:51:23 2023 -0400

    initial commit

git status

 git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   index.qmd

publish to github

existing project, github first

publish to github: setup

git remote add origin https://github.com/edavidaja/intro-git.git
git branch -M main

git push

 git push -u origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 418 bytes | 418.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/edavidaja/intro-git.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

all together now

mkdir intro-git
cd intro-git
git init
touch _quarto.yml
git stage _quarto.yml
git commit -m "added quarto yml"
touch index.qmd
git stage index.qmd
git commit -m "added quarto document"

create intro-git on GH
follow instructions to push

10:00

.gitignore

.Renviron
.env
.Rproj.user
*.csv
data/

tools

launchers

terminals

cross-platform

alacritty

shell helpers

command line interfaes

editors

git GUIs

Recommended Git Clients

how?!

personal radmin

workflows: II

branch

mainexperiment0-36694691-1d908ce2-052a2463-6c51b1c

create a branch

all equivalent:

 git branch new_branch
 git checkout new_branch
Switched to branch 'new_branch'



 git checkout -b new_branch
Switched to a new branch 'new_branch'



 git switch --create new_branch
Switched to a new branch 'new_branch'

git status

 git status
On branch new_branch
nothing to commit, working tree clean

back to main

 git checkout main
Switched to branch 'main'



 git switch main
Switched to branch 'main'

multiverse

  • checkout new_branch
  • edit an existing file
  • commit
  • switch back to main
10:00

commit on branch

 git commit -am "commit on a branch"
[new_branch f1c234b] commit on a branch
 1 file changed, 3 insertions(+)

 cat index.qmd
---
title: happy git
---

 git checkout main
Switched to branch 'main'

 cat index.qmd

merge

mainexperiment0-31375711-d16ae9e2-294b8333-48f02af

git merge

git merge new_branch
 git merge new_branch
Updating 7614b5c..f1c234b
Fast-forward
 index.qmd | 3 +++
 1 file changed, 3 insertions(+)

PRs

  • checkout second_branch
  • edit an existing file
  • commit
  • push the branch to GitHub

--set-upstream

 git push
fatal: The current branch second-branch has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin second-branch

To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.

git config

git config --global push.autoSetupRemote true


I set this globally because my workflow is pretty basic, ymmv

git push -u

 git push -u origin second-branch
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a pull request for 'second-branch' on GitHub by visiting:
remote:      https://github.com/edavidaja/intro-git/pull/new/second-branch
remote:
To https://github.com/edavidaja/intro-git.git
 * [new branch]      second-branch -> second-branch
branch 'second-branch' set up to track 'origin/second-branch'.

permissions & project management

unhappy paths

push rejection

  • make a new file locally, then try to push to GH
 git push
To https://github.com/edavidaja/intro-git.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/edavidaja/intro-git.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
02:00

merge strategy

 git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 636 bytes | 212.00 KiB/s, done.
From https://github.com/edavidaja/intro-git
   2bdda53..424444e  main       -> origin/main
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.

merge conflicts

mainexperiment0-505879b1-55b10a22-556dc6d3-b45b5fe4-a6c4f8e

merge conflict

  • modify a file on GH
  • modify the same file locally
 git pull --rebase
Auto-merging main.R
CONFLICT (content): Merge conflict in main.R
error: could not apply 160ea3e... added tidyverse
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 160ea3e... added tidyverse
02:00

<<<<<<< HEAD
library(shiny)
||||||| parent of 160ea3e (added tidyverse)
=======
library(tidyverse)
>>>>>>> 160ea3e (added tidyverse)