class: center, middle, inverse, title-slide # Git With The Times ### Manuel Alcala Kovalski ### 2022-02-24 --- <style type="text/css"> .highlight-last-item > ul > li, .highlight-last-item > ol > li { opacity: 0.5; } .highlight-last-item > ul > li:last-of-type, .highlight-last-item > ol > li:last-of-type { opacity: 1; } </style> .left-column[ # Can you relate to this? ] .right-column[ <img src="imgs/what-is-version-control.gif" width="550px" height="550px" style="display: block; margin: auto;" /> ] ??? This comic is an illustratioin of me when I was writing my senior thesis Really wish I had known about Git then! But this problem is still pretty frequent --- .left-column[ # How about this? ] .right-column[ <img src="imgs/final-data.jpeg" style="display: block; margin: auto;" /> ] ??? Always happens with multiple people working on spreadsheets --- # Git & GitHub to the rescue .pull-left[ Today we'll go over how Git & GitHub can help you + Backup your work + Keep track of your files + Give a web presence to your projects + Try out new changes without fear + Collaborate effectively We will also cover + Key concepts + How to set up Git projects in R + Basic mechanics of the git workflow ] .pull-right[ <img src="imgs/git-management.png" width="500px" height="450px" style="display: block; margin: auto;" /> ] ??? --- # So what is Git? .bg-washed-green.b--dark-green.ba.bw2.br3.shadow-5.ph4.mt5[ Git is a __version control system__. Its original purpose was to help groups of developers work collaboratively on big software projects. Git manages the evolution of a set of files – called a __repository__ or repo – in a sane, highly structured way. It is like the “Track Changes” feature from Microsoft Word, but more rigorous, powerful, and scaled up to multiple files. .tr[ — Jennifer Bryan, [_Excuse me, do you have a moment to talk about version control?_](https://peerj.com/preprints/3159v2/) ]] ??? Git is a version control system Structures our projects Facilitates collaboration Track changes on steroids --- # How is Git different from GitHub? .pull-left[ <img src="imgs/github-logo.png" height="200px" style="display: block; margin: auto;" /> + __GitHub__ is a __hosting service__ that provides a Git-aware home for such projects on the internet. + It's ike DropBox or Google Drive, but more structured, powerful, and programmatic. ] -- .pull-right[ <img src="imgs/git-logo.png" width="350px" height="200px" style="display: block; margin: auto;" /> + __Git__ is the software you will use __locally__ to record changes to a set of files. + When you use __GitHub__, __Git__ is always doing its things behind the scenes ] --- class: center, middle, inverse, title-slide-ggbrookings # Let's Git Started: Key Concepts --- # Repository + A repository is a directory of files that Git manages holistically -- + You can use __Git__ to take snapshots (version control) of all the files in your repository -- + With __GitHub__ your repo con live on your computer and on the web <img src="imgs/git-brownbag-repo.png" height="400px" style="display: block; margin: auto;" /> ??? This is a screenshot of the repository for this presentation --- # Remote .pull-left[ + You should always back up your work, ideally somewhere different than your local drive. In __Git__, this place is called the __remote repository__ + __GitHub__ is just a very popular __remote__ + Some alternative remotes are: + [Bitbucket](https://bitbucket.org) + [GitLab](https://about.gitlab.com) ] .pull-right[ <img src="imgs/remotes.png" style="display: block; margin: auto;" /> ] --- # Remote .pull-left[ + It's really easy to create one from GitHub + Click on _your repositories > New_ + Choose some options to initialize your repository ] -- .pull-right[ <img src="imgs/create-repo.png" style="display: block; margin: auto;" /> ] --- # Cloning .left-column[To get some work from a __remote__ for the first time you need to __clone__ it This is a fancy term for downloading a local copy of the repo] .right-column[ <img src="imgs/cloning.png" style="display: block; margin: auto;" /> ] ??? If we want to have the repository on our computer we need to clone it Cloning is like downloading all the files but also their entire history --- # Git Areas .pull-left[ + Once we start making changes to the __repo__ we __cloned__, these changes will exist in one of the three core __areas__ to Git: + __Working Tree__ (a.k.a untracked area) + __Staging Area__ (a.k.a the index) + __Local Repository__ + Files and modifications will travel from the __Working Tree__ to the __Staging Area__ and finish at the __Local Repository__. ] .pull-right[ <img src="imgs/git-areas.png" style="display: block; margin: auto;" /> ] ??? Lifecycle of our changes --- # The Working Tree + This is the area where you are currently working. -- + If you make changes to files in your __working tree__ Git will recognize that they are modified, but won't save anything that goes on in them + This is why some people call it the “__untracked__” area of git. -- + Git will only start __tracking__ our files once we explicitly tell it to. -- .pull-left[ You can check where your files are with: ```r gert::git_status() ``` ] .pull-right[ <br> <PRE class="fansi fansi-output"><CODE>#> <span style='color: #555555;'># A tibble: 7 × 3</span> #> file status staged #> <span style='color: #555555; font-style: italic;'><chr></span> <span style='color: #555555; font-style: italic;'><chr></span> <span style='color: #555555; font-style: italic;'><lgl></span> #> <span style='color: #555555;'>1</span> git_brownbag.Rproj modified FALSE #> <span style='color: #555555;'>2</span> imgs/collaborative-work.png new FALSE #> <span style='color: #555555;'>3</span> imgs/example-repo.png new FALSE #> <span style='color: #555555;'>4</span> imgs/final-data.jpeg new FALSE #> <span style='color: #555555;'>5</span> index.html modified FALSE #> <span style='color: #555555;'>6</span> index.Rmd modified FALSE #> <span style='color: #555555;'>7</span> remark.css modified FALSE </CODE></PRE> ] --- # Staging Area The __Staging Area__ is where Git starts tracking and saving changes that occur in files. ??? If your workflow is to commit every changed file whenever its time to commit then you wont need staging and can just use git commit -am “another bunch of edits” But if you want to review the changes you did before committing then I can recommend reviewing changes to each file and then add them to staging. When you are satisfied with you change set then you can commit your staging area. Sometimes you end up with multiple unrelated changes in your working copy. Using staging can help you sort your changes to relevant feature branches. -- + You tell __Git__ you want to track these specific files -- + __Git__ moves them from your __Working Tree__ to the __Staging Area__ and says “Cool, I know about this file in its entirety.” -- + Staging can help us group related changes and make our commits smaller --- # Local Repository + The area that saves everything -- + That's it... -- + Now we're ready to add our __staged changes__ to the __local repository__ by __committing__ them. --- # Don't be afraid of commitment + When you want to take a snapshot of a file, you create a **commit** -- + A __commit__ is equivalent to saving a version of a file(s) -- + Every time you make a commit you must also write a short commit message. Ideally, this conveys the motivation for the change -- + Commiting frequently will save you lots of headaches <img src="imgs/commits-iris.png" height="300px" style="display: block; margin: auto;" /> --- class: center, middle, inverse, title-slide-ggbrookings ## So far everything has been very linear ??? You make changes to a file, group them, commit them But in reality we'll change our mind, make mistakes, and coordinate with making changes with multiple people --- class: center, middle, inverse, title-slide-ggbrookings # Let's branch out and try new things ??? The really cool part about Git is that it lets us try out stuff --- # Branching Out + A __branch__ is an independent line of development within a repo -- + They are useful for trying out stuff since they're really easy to throw away if you decide against your changes -- .left-column[ + You can use __branches__ to work as a team on a new feature for your project! ] .right-column[ <img src="imgs/fim-branch.png" style="display: block; margin: auto;" /> ] ??? Talk about FIM It's common for the master to be posted somewhere so to not mess up the live version we sometimes work on branches --- # Branching Out .left-column[ + The __default__ branch is called the __master branch__ ] .right-column[ <img src="imgs/master-branch.png" style="display: block; margin: auto;" /> ] --- # Branching Out .left-column[ + The __default__ branch is called the __master branch__ + You can add (and discard) your own branches ] .right-column[ <br><br> <img src="imgs/feature-branch.png" style="display: block; margin: auto;" /> ] --- # Branching Out .left-column[ + You can add your own branches too + The __default__ branch is called the __master branch__ + You'll often do a lot of work on a branch ] .right-column[ <img src="imgs/wild-experiment-branch.png" style="display: block; margin: auto;" /> ] ??? For example: I want to add some new theme functions and color palettes to my package. Or I want to refactor some old code and also need to make some new charts. Can work on these in separate branches. --- # Merging your changes > It's common for the master branch to be what you have published or finalized whereas other branches can contain work in progress .pull-left[ + Once you finish your work on a branch, you'll want to get it back into the master branch + To get changes from one branch into another, you __merge__ them + __Merges__ help manage combining your work with someone else's ] .pull-right[ <img src="imgs/merge.png" style="display: block; margin: auto;" /> ] --- class: middle, center ## Git’s model of file management may seem uncomfortably rigid --- class: middle, center ## But it will be worth it once we start collaborating ??? What's really powerful about Git is that it enables the distribution of files across different people, computers, and time. Once you consider the overhead of working with other people (including your future self) the pros of Git will be worth the learning curve --- class: center, middle, inverse, title-slide-ggbrookings # Collaborating with Git & GitHub: # You'll never _work_ alone --- # Adding Contributors .pull-left[ + As the __owner__ of a repo you can: + Add collaborators with permission to __read/write files__ in the repo, create __branches__, and __merge__ changes directly ] .pull-right[ <img src="imgs/contributors.png" height="300px" style="display: block; margin: auto;" /> ] --- # _Git_ everyone on the same page .pull-left[ + **Fetch** changes to the **remote repository** to see if any modified files are not on your computer + __Pull__ them from the remote repository on GitHub if you want those changes to take effect on your computer. ] .pull-right[ <img src="imgs/fetch-v-pull.jpeg" style="display: block; margin: auto;" /> ] ??? I'm working on some changes and I want other people to have them. First need to ensure I have the most recent files If not, I can pull those changes and then push my changes You can think of fetching as putting an item in your shopping chart and pulling as buying it and taking it home with you -- .pull-left[ + __Push__ your changes to the __remote__ if _you_ make a commit that you want others to __pull__ ] --- # Pull Requests and Forks + __Pull request__ is a GitHub-specific way to propose changes to a repo with facilities for structured review. + They can be made between + Two __branches__ in the same repo + Two independent copies of a repo, an original and a __“fork”__. ??? PR's comes up when contributing to other people's projects A GitHub fork is a copy of a repository (repo) that sits in your account rather than the account from which you forked the data from. -- .large[We'll go over an example soon] --- class: center, middle, inverse, title-slide-ggbrookings # Integrating Git & GitHub with R --- # What are our options? + You can choose from several options when using Git/GitHub: -- + Command-line (Terminal) -- + GitHub Desktop App (Available from the Software Center) -- + RStudio -- + Since I do most of my work in `R`, I'd rather not have to open a new program just to use Git. -- + You can use: + The RStudio git pane for a point and click -- + Packages to facilate git workflows. I highly recommend __{`gert`}__ and __{`usethis`}__ --- # Setting Up a New Project .pull-left[ + If you want to use the RStudio interface to control Git, you need to create an __RStudio Project__ + Create a new RStudio Project from the upper-right corner of the RStudio IDE window, choosing _New Project_ ] .pull-right[ <img src="imgs/new-project.png" style="display: block; margin: auto;" /> ] --- # Setting Up a New Project .pull-left[ + If you want to use the RStudio interface to control Git, you need to create an __RStudio Project__ + Create a new RStudio Project from the upper-right corner of the RStudio IDE window, choosing _New Project_ + Choose _Empty Project_ ] .pull-right[ <img src="imgs/empty-project.png" style="display: block; margin: auto;" /> ] --- # Setting Up a New Project .pull-left[ + If you want to use the RStudio interface to control Git, you need to create an __RStudio Project__ + Create a new RStudio Project from the upper-right corner of the RStudio IDE window, choosing _New Project_ + Choose _Empty Project_ + Check the option _Create a git repository_ before clicking _Create Project_ ] .pull-right[ <img src="imgs/create-project.png" style="display: block; margin: auto;" /> ] --- # What about my old projects? .pull-left[ + It's not too late to set up git on your existing projects!! + Again, create a project but this time choose _Existing Directory_ ] .pull-right[ <img src="imgs/existing-directory.png" style="display: block; margin: auto;" /> ] --- # What about my old projects? .pull-left[ + It's not too late to set up git on your existing projects!! + Again, create a project but this time choose _Existing Directory_ + Go to the _Tools menu_ -> _Version Control_ -> _Project Setup_… ] .pull-right[ <img src="imgs/project-setup.png" style="display: block; margin: auto;" /> ] --- # What about my old projects? .pull-left[ + It's not too late to set up git on your existing projects!! + Again, create a project but this time choose _Existing Directory_ + Go to the _Tools menu_ -> _Version Control_ -> _Project Setup_… + This will open a new window. Change the _None_ setting by choosing _Git_ from the drop-down menu ] .pull-right[ <img src="imgs/choose-git.png" style="display: block; margin: auto;" /> ] -- ### Congratulations, your project has Git versioning enabled!🎉🎉🎉 --- # Using Git from RStudio .pull-left[ + A “Git” tab should have been added to your interface next to “Environment” and “History” tabs + Note the __.gitignore file__ automatically generated by RStudio—it lists all file formats you do _not_ want to track. + You can edit this document to add any type of file you would like git not to track. ```r usethis::edit_git_ignore(scope = 'project') ``` ] .pull-right[ <img src="imgs/git-pane.png" style="display: block; margin: auto;" /> ] --- # Using Git from RStudio From the Git pane you can: .left-column[ + __Stage__ files ] .right-column[ <img src="imgs/staging.png" style="display: block; margin: auto;" /> ] --- # Using Git from RStudio From the Git pane you can: .left-column[ + Stage files + __Commit__ them ] .right-column[ <img src="imgs/commiting.png" style="display: block; margin: auto;" /> ] --- # Using Git from RStudio From the Git pane you can: .left-column[ + Stage files + Commit them + __Push/Pull__ ] .right-column[ <img src="imgs/commiting.png" style="display: block; margin: auto;" /> ] --- # Using Git from RStudio From the Git pane you can: .left-column[ + Stage files + Commit them + Push/Pull + __Revert__ your changes ] .right-column[ <img src="imgs/revert-commit.png" style="display: block; margin: auto;" /> ] --- # Using Git from RStudio From the Git pane you can: .left-column[ + Stage files + Commit them + Push/Pull + Revert your changes + View your repo's __commit history__ ] .right-column[ <img src="imgs/commit-history.png" style="display: block; margin: auto;" /> ] --- # Git with R .pull-left[ + We can easily replicate the project setup we did with some nice functions from __`{usethis}`__ ] .pull-right[ ```r usethis::create_project('example-project') ✓ Setting active project to '/Users/malcalakovalski/example-project' ✓ Writing 'example-project.Rproj' ✓ Opening '/Users/malcalakovalski/example-project/' in new RStudio session ✓ Setting active project to '<no active project>' ``` ] ??? If you use Git a lot using the GUI can slow you down so I prefer using some code usethis is mainly used to automate things that come up when setting up a project --- # Using Git with R .pull-left[ + We can easily replicate the project setup we did with some nice functions from __`{usethis}`__ + Next, we must make our new project a __Git repository__ ] .pull-right[ <br><br><br> ```r usethis::use_git() ✓ Setting active project to '/Users/malcalakovalski/example-project' ✓ Initialising Git repo ✓ Adding '.Rhistory', '.Rdata', '.httr-oauth', '.DS_Store' to '.gitignore' ``` ] --- # Using Git with R .pull-left[ + We can easily replicate the project setup we did with some nice functions from __`{usethis}`__ + Next, we must make our new project a __git repository__ + Finally, we can create a __GitHub repository__ ] .pull-right[ <br><br><br> <br><br><br> ```r usethis::use_github() ✓ Setting active project to '/Users/malcalakovalski/example-project' ✓ Creating GitHub repository 'malcalakovalski/example-project' ✓ Setting remote 'origin' to 'git@github.com:malcalakovalski/example-project.git' ✓ Pushing 'master' branch to GitHub and setting 'origin/master' as upstream branch ✓ Opening URL 'https://github.com/malcalakovalski/example-project' ``` ] --- background-image: url(imgs/example-github.png) background-size: contain background-size: 85%, 20% # ✅ Now people can __clone__ or __fork__ our repo! --- # Contributing to someone else's projects >Recall: A __pull request__ is how you propose a change to a GitHub repository. Think of it as a _request_ for the maintainer to _pull_ your changes into their repo. -- + We will suggest changes to the __README__ file on a toy __GitHub repo__ I creatively titled `example-repo`. -- + The __README__ simpy says "Example repo" which is not very descriptive. -- + We will propose a slightly more informative opening sentence. --- # This is what the repo looks like right now <img src="imgs/example-repo.png" style="display: block; margin: auto;" /> --- # Our First Pull Request .pull-left[ + First, __fork__ the repository to get your own copy on GitHub, and then __clone__ that, to get your own local copy. ] .pull-right[ ```r usethis::create_from_github('https://github.com/mgalcala/example-repo', fork = TRUE) ✓ Creating '/Users/malcalakovalski/Documents/Projects/example-repo/' ✓ Forking 'mgalcala/example-repo' ✓ Cloning repo from 'git@github.com:malcalakovalski/example-repo.git' into '/Users/malcalakovalski/Documents/Projects/example-repo' ✓ Setting active project to '/Users/malcalakovalski/Documents/Projects/example-repo' ℹ Default branch is 'main' ✓ Adding 'upstream' remote: 'git@github.com:mgalcala/example-repo.git' ✓ Pulling changes from 'upstream/main'. ✓ Setting remote tracking branch for local 'main' branch to 'upstream/main' ✓ Writing 'example-repo.Rproj' ✓ Adding '.Rproj.user' to '.gitignore' ✓ Opening '/Users/malcalakovalski/Documents/Projects/example-repo/' in new RStudio session ✓ Setting active project to '<no active project>' ``` ] --- # Our First Pull Request .pull-left[ + First, __fork__ the repository to get your own copy on GitHub, and then __clone__ that, to get your own local copy. + Next start the __pull request__ with __`pr_init()`__, which creates a branch in our pull request repository and switches to it (or __"checks it out"__). ] .pull-right[ ```r pr_init(branch = 'feature-improve-readme') ``` ```r ✓ Setting active project to '/Users/malcalakovalski/Documents/Projects/example-repo' ✓ Pulling changes from 'upstream/main'. ✓ Creating and switching to local branch 'feature-improve-readme'. • Use `pr_push()` to create a PR. ``` ] -- ### ✅ Now we can work locally, make changes to files and commit hem to Git --- # Pull Request Workflow .left-column[ + Change the __README__ ] .right-column[ We write "Example repo used in the Brookings Data Network Git brownbag to demonstrate the workflow of creating a pull" ] --- # Pull Request Workflow .left-column[ + Change the __README__ + See our files in the __working tree__ ] .right-column[ <br><br> ```r gert::git_status() ``` <PRE class="fansi fansi-output"><CODE>#> <span style='color: #555555;'># A tibble: 3 × 3</span> #> file status staged #> <span style='color: #555555; font-style: italic;'><chr></span> <span style='color: #555555; font-style: italic;'><chr></span> <span style='color: #555555; font-style: italic;'><lgl></span> #> <span style='color: #555555;'>1</span> .gitignore new FALSE #> <span style='color: #555555;'>2</span> example-repo.Rproj new FALSE #> <span style='color: #555555;'>3</span> README.md modified FALSE </CODE></PRE> ] --- # Pull Request Workflow .left-column[ + Change the __README__ + See our files in the __working tree__ + __Stage__ them ] .right-column[ <br><br><br><br><br><br> ```r # Stage a specific file gert::git_add(files = 'README.md') # Stage every file in the working tree gert::git_add(files = '.') ``` ] --- # Pull Request Workflow .left-column[ + Change the __README__ + See our files in the __working tree__ + __Stage__ them + __Commit__ them ] .right-column[ <br><br><br><br><br><br><br><br> ```r gert::git_commit(message = 'Added information on what the repository is for') ``` ] --- # Pull Request Workflow .left-column[ + Change the __README__ + See our files in the __working tree__ + __Stage__ them + __Commit__ them ] .right-column[ 😎 __Tip:__ We can combine the staging and commiting steps with ```r gert::git_commit_all(message = 'your commit message') 😎 ``` ] --- # Usual Git Workflow for Collaboration + If we had ownership over the repository, we could __push__ our changes to our collaborators with __`gert::git_push()`__ -- + In turn, they would be able __fetch__ and then __pull__ our changes with __`gert::git_fetch()`__ and __`gert::git_pull()`__ -- + Since we are not direct collaborators to the project, our workflow will be a little different. --- # Sending Over Our Suggestion .pull-left[ + __Push__ the local change to our copy of _example-repo_ on GitHub using __`usethis::pr_push()`__ ] .pull-right[ ```r usethis::pr_push() ✓ Setting active project to '/Users/malcalakovalski/Documents/Projects/example-repo' ✓ Pushing local 'feature-improve-readme' branch to 'origin' remote. • Create PR at link given below ✓ Opening URL 'https://github.com/malcalakovalski/example-repo/compare/feature-improve-readme' ``` This launches a browser window at the specified URL and we need to click on where it says __"Create Pull Request"__ ] --- # Sending Over Our Suggestion .pull-left[ + __Push__ the local change to our copy of _example-repo_ on GitHub using __`usethis::pr_push()`__ + GitHub will ping the project owner and they will review our pull request. We can view this pull request in the browser with `usethis::pr_view()` ] .pull-left[ <img src="imgs/pr-push.png" style="display: block; margin: auto;" /> ] --- class: center, middle, inverse, title-slide-ggbrookings ### If our _pull request_ is perfect, the maintainer will accept it (i.e. _merge_ it). <br> --- class: center, middle, inverse, title-slide-ggbrookings ### ⚠️ Alas, there was an omission in our commit: ### Instead of writing _"pull request"_ we wrote _"pull" _ <img src="imgs/diff.png" height="550px" style="display: block; margin: auto;" /> --- background-image: url(/imgs/pr-review.png) background-size: contain background-position: bottom background-size: 65%, 20% ### 🚨🚨🚨 Since our pull request had a missing word, the project owner leaves us some comments requesting changes. --- ## Responding to our PR Review We can then go back and complete the sentence, commit the correction, and push them back with __`usethis::pr_push()`__ <img src="imgs/pr-response.png" style="display: block; margin: auto;" /> --- ## Reviewing a Pull Request + Now the reviewer gets another chance to review our changes. + At this point they might choose to just make the necessary changes themselves and push their commits into our pull request to finish things up. -- + The reviewer can fetch the pull request to their local machine with __`usethis::pr_fetch()`__ -- + Fetching the PR creates a local branch for them called _`malcalakovalski-feature-improve-readme`_ -- + Once the reviewer makes the necessary changes they run __`pr_push()`__ to push their changes into our PR -- + Finally, the reviewer merges our pull request on GitHub by running __`pr_finish()`__ ```r #> ✔ Checking that remote branch 'malcalakovalski-feature-improve-readme' has the changes in 'local/malcalakovalski-feature-improve-readme' #> ✔ Switching back to 'master' branch #> ✔ Pulling changes from GitHub source repo 'origin/master' #> ✔ Deleting local 'malcalakovalski-feature-improve-readme' branch #> ✔ Removing remote 'mine-cetinkaya-rundel' ``` --- # Pulling Reviewer Changes + Since the reviewer has contributed some code to our pull request, we can get that code back to our computer with __`usethis::pr_pull()`__ -- + This feature can be useful in PRs if there are a few rounds of alternating contributions from you and the maintainer -- + In this case it is optional, since the full PR has already been incorporated into the default branch of the source repo. --- class: center, middle, inverse, title-slide-ggbrookings #We have successfully contributed to a project! 🎉🎉🎉 --- # Shameless Plug: Help me help you + If you use __`{ggbrookings}`__ and are having trouble, please submit an __issue__ on GitHub + Posting an issue gives me an opportunity to respond to your questions in a public forum that others can benefit from too! + Even better, if you have a suggestion for a new feature or an improvement to the package please submit a __pull request__! --- class: center, middle, inverse, title-slide-ggbrookings #Thank you for your time! 🤗🤗🤗