diff --git a/foundations/github/git-branches.md b/foundations/github/git-branches.md index 8bf0a8dec..056c7e614 100644 --- a/foundations/github/git-branches.md +++ b/foundations/github/git-branches.md @@ -1,6 +1,12 @@ +```{image} ../../images/Git-Logo-2Color.png +:alt: Git Logo +:width: 600px +:align: center +``` + # Git Branches -The best practices for a simple workflow for suggesting changes to a GitHub repository are: create your own fork of the repository, make a branch from your fork where your changes are made, and then suggest these changes move to the upstream repository with a pull request. This section of the GitHub chapter assumes you have read the prior GitHub sections, are at least somewhat familiar with git commands and the vocabulary ("cloning," "forking," "merging," "pull request" etc), and that you have already created your own fork of the [GitHub Sandbox Repository](https://github.com/ProjectPythia/github-sandbox) hosted by Project Pythia. That fork is where you will make your first Git branch while following along with this chapter. +Git "branches" are an important component of many Git and GitHub workflows. If you plan to use GitHub to manage your own resources, or contribute to a GitHub hosted project, it is essential to have a basic understanding of what branches are and how to use them. For example, the best practices for a simple workflow for suggesting changes to a GitHub repository are: create your own fork of the repository, make a branch from your fork where your changes are made, and then suggest these changes move to the upstream repository with a pull request. This section of the GitHub chapter assumes you have read the prior GitHub sections, are at least somewhat familiar with git commands and the vocabulary ("cloning," "forking," "merging," "pull request" etc), and that you have already created your own fork of the [GitHub Sandbox Repository](https://github.com/ProjectPythia/github-sandbox) hosted by Project Pythia. That fork is where you will make your first Git branch while following along with this chapter. ## Overview: @@ -9,8 +15,9 @@ The best practices for a simple workflow for suggesting changes to a GitHub repo 1. Switching Branches 1. Setting up a Remote Branch 1. Merging Branches -1. Pulling 1. Deleting Branches +1. Updating Your Branches +1. Complete Workflow ## Prerequisites @@ -21,7 +28,7 @@ The best practices for a simple workflow for suggesting changes to a GitHub repo | [Issues and Discussions](github-issues) | Recommended | | | [Cloning and Forking a Repository](github-cloning-forking) | Necessary | | | [Advanced GitHub Setup](github-setup-advanced) | Recommended | | -| [Basic Version Control with Git](basic-git) | Recommended | | +| [Basic Version Control with Git](basic-git) | Necessary | | - **Time to learn**: 30 minutes @@ -31,14 +38,16 @@ The best practices for a simple workflow for suggesting changes to a GitHub repo Git branches allow for non-linear or differing revision histories of a repository. At a point in time, you can split your repository into multiple development paths (branches) where you can make different commits in each, typically with the ultimate intention of merging these branches and development changes together at a later time. -Branching is one of git's methods for helping with collaborative document editing, much like "change tracking" in Google Docs or Microsoft Word. It enables multiple people to edit copies of the same document content, while reducing or managing edit collisions, and with the ultimate aim of merging everyones changes together later. It also allows the same person to edit multiple copies of the same document, but with different intentions. Some reasons for wanting to split your repository into multiple paths (i.e. branches) is to experiment with different methods of solving a problem (before deciding which method will ultimately be merged) and to work on different problems within the same codebase (without confusing which code changes are relevant to which problem). There are also some convenience bots on GitHub that, if installed in the repository, may not act as intended if your work is all on the `main` branch. +Branching is one of git's methods for helping with collaborative document editing, much like "change tracking" in Google Docs or Microsoft Word. It enables multiple people to edit copies of the same document content, while reducing or managing edit collisions, and with the ultimate aim of merging everyone's changes together later. It also allows the same person to edit multiple copies of the same document, but with different intentions. Some reasons for wanting to split your repository into multiple paths (i.e. branches) is to experiment with different methods of solving a problem (before deciding which method will ultimately be merged) and to work on different problems within the same codebase (without confusing which code changes are relevant to which problem). -These branches can live on your computer (local) or on GitHub (remote). They are brought together through Git _pushes_, _pulls_, and _pull requests_. _Pushing_ is how you transfer changes from your local repository to a remote repository. _Pulling_ is how you fetch upstream changes into your branch. And _Pull Requests_ are how you suggest the changes you've made on your branch to the upstream codebase. +These branches can live on your computer (local) or on GitHub (remote). They are brought together through Git _pushes_, _pulls_, _merges_, and _pull requests_. _Pushing_ is how you transfer changes from your local repository to a remote repository. _Pulling_ is how you fetch upstream changes into your branch. _Merging_ is how you piece the forked history back together again (i.e. join two branches). And _Pull Requests_ are how you suggest the changes you've made on your branch to the upstream codebase. -One rule of thumb is for each development feature to have its own development branch until that feature is ready to be added to the upstream (remote) codebase. This allows you to compartmentalize your pull requests so that smaller working changes can be merged upstream independently of one another. For example, you might have a complete or near-complete feature on its own branch with an open pull request awaiting review. While you wait for feedback from the team before merging it, you can still work on a second feature on a second branch without affecting your first feature's pull request. **We encourage you to always do your work in a designated branch.** +```{admonition} Pull Requests +:class: info +We will cover [Pull Requests]((github-pull-request)) more in-depthly in the next section. +``` -![basic branch](../../images/basicbranch.png) -The above flowchart demonstraties commits (C1 through C5) added to different branches of a personal fork of the upstream main repository. Different commits can be added to either branch in any order without depending on or knowing about each other. +One rule of thumb is for each development feature to have its own development branch until that feature is ready to be added to the upstream (remote) codebase. This allows you to compartmentalize your pull requests so that smaller working changes can be merged upstream independently of one another. For example, you might have a complete or near-complete feature on its own branch with an open pull request awaiting review. While you wait for feedback from the team before merging it, you can still work on a second feature on a second branch without affecting your first feature's pull request. **We encourage you to always do your work in a designated branch.** ## Creating a New Branch @@ -47,6 +56,9 @@ The above flowchart demonstraties commits (C1 through C5) added to different bra Having forked (NOT just cloned) the [GitHub Sandbox Repository](https://github.com/ProjectPythia/github-sandbox) is essential for following the steps in this book chapter. See the chapter on [GitHub Cloning and Forking](github-cloning-forking.md). ``` +![branching](../../images/branching.gif) +The above flowchart demonstrates forking a remote repository, labeled "Upstream", creating a local copy, labeled "Clone", creating a new branch, "branchA", and adding two commits, C3 and C4, to "branchA" of the local clone of the forked repository. Different commits can be added to different branches in any order without depending on or knowing about each other. + From your terminal, navigate to your local clone of your `Github-Sandbox` Repository fork: ``` @@ -91,7 +103,7 @@ You will see one local branch (`main`) and your remote branch (`remotes/origin/H Now, before we make some sample changes to our codebase, let's create a new branch where we'll make these changes: ``` -git branch newbranch +git branch branchA ``` Check that this branch was created with: @@ -102,14 +114,14 @@ git branch ![Git NewBranch](../../images/4-gitnewbranch.png) -This will display the current and the new branch. You'll notice that we are still on branch `main` and will need to switch branches to work in our `newbranch`. +This will display the current and the new branch. You'll notice that current or active branch, indicated by the "\*" is still the `main` branch. Thus, any changes we make to the contents of our local repository will still be made on `main`. We will need to switch branches to work in the new branch, `branchA`. ## Switching Branches To switch branches use the command `git checkout` as in: ``` -git checkout newbranch +git checkout branchA ``` To check your current branch use `git status`: @@ -124,7 +136,12 @@ Notice that `git status` doesn't say anything about being up-to-date, as before. ## Setting up a Remote Branch -Before we push this branch upstream, let's make some sample changes by creating a new empty file, with the ending ".py". +While your clone lives locally on your laptop, a remote branch exists on your GitHub server. You have to tell GitHub about your local branch before these changes are reflected remotely in your upstream fork. + +![pushing](../../images/pushing.gif) +The above flowchart demonstrates pushing two new local commits (C3 and C4) to the corresponding remote branch. Before the push, the changes from these commits exist ONLY locally and are not represented on your upstream GitHub repository. After the push, everything is up-to-date. + +Before we push this branch upstream, let's make some sample changes (like C3 or C4) by creating a new empty file, with the ending ".py". ``` touch hello.py @@ -152,12 +169,12 @@ git push ![Git Push](../../images/6c-gitpush.png) -You will get an error message, "fatal: The current branch newbranch has no upstream branch." So what is the proper method for getting our local branch changes up to GitHub? +You will get an error message, "fatal: The current branch `branchA` has no upstream branch." So what is the proper method for getting our local branch changes up to GitHub? First, we need to set an upstream branch to direct our local push to: ``` -git push --set-upstream origin newbranch +git push --set-upstream origin branchA ``` Thankfully, Git provided this command in the previous error message. @@ -172,82 +189,72 @@ Notice the new branch called `remotes/origin/newbranch`. And when you do a `git On future commits you will not have to repeat these steps, as your remote branch will already be established. Simply push with `git push` to have your remote branch reflect your future local changes. -![remote](../../images/remote.png) -The above flowchart demonstrates adding commits locally (C3 and C4) before pushing them to the corresponding remote branch. - ## Merging Branches -At this point, we will demonstrate how to merge branches via a Pull Request. Merging is how you bring your split branches of a repository back together again. - -![PR](../../images/PR.png) -The above flowchart demonstrates a simple Pull Request (PR1), the upstream main repository has accepted the changes from the Feature 2 branch of your fork. The latest commit to the Upstream Main repository is now C4. Your Feature2 branch can now be safely deleted. This flowchart has simplified out the remote and local versions of the Feature2 branch. - -The demonstration will move from your local terminal to GitHub. Go to your fork of the [GitHub Sandbox Repository](https://github.com/ProjectPythia/github-sandbox). One fast way to get to your fork, is to click the "fork" button and then follow the link underneath the message, "You've already forked github-sandbox." - -When you've navigated to your fork, you should see a message box alerting you that your branch `newbranch` had recent changes with the option to generate an open pull request. This pull request would take the changes from your `newbranch` branch and suggest them for the original upstream ProjectPythia github-sandbox repository. You'll also notice that you are on branch `main`, but that there are now 2 branches. - -![GitHub](../../images/8-github.png) - -If you click on the branch `main` you'll see the list of these branches. - -![GitHub Branches](../../images/9-github-seebranches.png) +Merging is how you bring your split branches of a repository back together again. -There you can click on the branch `newbranch` to switch branches. +If you want to merge two _local_ branches together, the steps are as follows: -![New Branch](../../images/10-github-newbranch.png) +Let's assume your two branches are named `branchA` and `branchB`, and you want your changes from `branchB` to now be reflected in `branchA` -Here you will see the message, "This branch is 1 commit ahead of ProjectPythia:main." Next to this message you'll see either the option to "Contribute" (which opens a pull request) or "Fetch Upstream" (which pulls in changes from the original repository). And just above your files you'll see your most recent commit. +1. First checkout the branch you want to merge INTO: -Click on the "Open a Pull Request" button under the "Contribute" drop-down. - -![Contribute](../../images/11-newbranch-contribute.png) - -This will send you to a new page. Notice that you are now in "ProjectPythia/github-sandbox" and not your fork. - -![Compare](../../images/12-compare.png) +``` +git checkout branchA +``` -The page will have the two branches you are comparing with an arrow indicating which branch is to be merged into which. Here, `base` is the upstream origin and `head` is your forked repository. If you wanted, you could click on these branches to switch the merge configuration. Underneath that you'll see a green message, "Able to merge. These branches can be automatically merged." This message means that there are no conflicts. We will discuss conflicts in a later chapter. +2. Then execute a `merge`: -In a one-commit pull request, the pull request title defaults to your commit message. You can change this if you'd like. There is also a space to add a commit message. This is your opportunity to explain your changes to the owners of the upstream repository. +``` +git merge branchB +``` -![Message](../../images/13-message.png) +If there were competing edits in the 2 branches that Git cannot automatically resolve, a **merge conflict** occurs. This typically happens if edits are to the same line in different commits. Conflicts can be [resolved in the command line](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line) or in your GUI of choice (such as Visual Studio Code). -And if you scroll down, you'll see a summary of this pull request with every commit and changed file listed. +A **Pull Request** is essentially a merge that happens on an upstream remote. We will continue this demonstration and cover the specifics of merging via a [Pull Request](github-pull-request) more thoroughly in the next section. -![Summary](../../images/14-prsummary.png) +![PR](../../images/pullrequest.gif) +The above flowchart demonstrates a simple Pull Request where the upstream main repository has accepted the changes from the feature branch of your fork. The latest commit to the Upstream Main repository is now C4. Your Feature branch can now be safely deleted. -Click the arrow next to "Create Pull Request" to change this to a draft pull request. +## Deleting Branches -![To Draft](../../images/15-todraft.png) +After the feature you worked on has been completed and merged, you may want to delete your branch. +![deletebranch](../../images/deletingbranch.gif) -Once you've clicked "Draft Pull Request," you will be directed to the page of your new pull request. Here you can add more comments or request reviews. +To do this locally, you must first switch back to `main` or any non-target branch. Then you can enter -![Draft PR](../../images/16-draft.png) +``` +git branch -d +``` -Clicking "Files Changed" allows you to see all of the changes that would be merged with this pull request. +for example -![Files](../../images/17-fileschanged.png) +``` +git branch -d branchA +``` -If you are working in a repository that has automatic checks, it is a good idea to wait for these checks to pass successfully before you request reviewers or change to a non-draft pull request. Do this by clicking "Ready for Review." +To delete the branch remotely, type -![Review](../../images/18-review.png) +``` +git push --delete . +``` -When working on a project with a larger team, do NOT merge your pull request before you have the approval of your teammates. Every team has their own requirements and best practice workflows, and will discuss/approve/reject pull requests together. We will cover more about the ways to interact with pull requests through conversations and reviews in a later section. +as in -To someone with write permissions on the repository, the ability to merge will look like this green button: -![Green](../../images/20-green.png) +``` +git push origin --delete jukent/branchA +``` -However, this pull request will NOT be merged, as the GitHub-Sandbox repository is intended to be static. +## Updating Your Branches -![remotePR](../../images/remotePR.png) -The above flowchart demonstrates a Pull Request (PR1) without simplifying out the remote vs local versions of the Feature2branch. Typically multiple pushes are made from your local to remote branch before a pull request is drafted to take all of those commits (C3, C4, C6, and C7) into the Upstream Main branch. +Previously, we showed you how to merge branches together, combining the changes from two different branches into one. Afterwards you deleted your feature branch `branchA`. Your local clone and fork of your `main` branch have now both need to pull from the upstream repository. -## Pulling +![pull](../../images/pulling.gif) +The above flowchart demonstrates pulling in the upstream changes from Upstream Main after a Pull Request has been merged, first into your fork and then into your clone. Before continuing to work, with new commits on the feature branch, it is best to pull in the upstream changes. -Once a team member's pull request has been merged, you will find that these upstream changes are not automatically included in your fork or your branches. In order to include the changes from the upstream main branch, you will need to do a `git pull`. +In this example, all of the changes to the branches were local and made by a single person, you. In a collaborative environment, other contributors may be making changes to their own feature branches (or main branch), which will ultimately be pushed up to the remote repository. Either way, your branches will become stale and need to be refreshed. The more time that passes by, the more likely this is to happen, particularly for an active GitHub repository. Here we show you how to sync your branches with the upstream branches. -![pull](../../images/pull.png) -The above flowchart demonstrates pulling in the upstream changes from Upstream Main after the pull request PR1 has been merged. Before continuing to work, with new commits (C6), it is best to pull in the upstream changes. The local vs remote branches have been simplified out of this diagram. +Once a pull request has been merged, you will find that these upstream changes are not automatically included in your fork or your other branches. In order to include the changes from the upstream main branch, you will need to do a `git pull`. First check if there are any upstream changes: @@ -255,7 +262,7 @@ First check if there are any upstream changes: git status ``` -Then, if there are no conflicts: +Then, if there are no merge conflicts: ``` git pull @@ -263,36 +270,22 @@ git pull `git pull` is a combination of `git fetch` and `git merge`. That is it updates the remote tracking branches (`git fetch`) AND updates your current branch with any new commits on the remote tracking branch (`git merge`). -![team](../../images/team.png) -The above flowchart demonstrates pulling in the upstream changes from Upstream Main in a team setting. Multiple authors will have their own feature branches that merge into the same Upstream Main repository by pull requests. It is important for each author to do regular `git pulls` to stay up to date with each other's contributions. The local vs remote branches have been simplified out of this diagram. +This same concept appplies to work in a team setting. Multiple authors will have their own feature branches that merge into the same Upstream Main repository via Pull Requests. It is important for each author to do regular `git pulls` to stay up to date with each other's contributions. -## Deleting Branches - -After the feature you worked on has been completed and merged, you may want to delete your branch. - -To do this locally, you must first switch back to `main` or any non-target branch. Then you can enter +## Complete Workflow -``` -git branch -d -``` +All in all your Git Branching workflow should resemble this flow: +![gitworkflow](../../images/gitworkflow.gif) -for example - -``` -git branch -d newbranch -``` - -To delete the branch remotely, type - -``` -git push --delete . -``` - -as in - -``` -git push origin --delete jukent/newbranch -``` +1. Forking the upstream repository +1. Creating a local clone of your upstream fork +1. Creating a new branch +1. Switching branches +1. Making a commit +1. Setting up a remote branch +1. Merging branches via a PR +1. Deleting branches +1. Pulling from upstream --- @@ -303,9 +296,10 @@ git push origin --delete jukent/newbranch ### What's Next? -Opening a Pull Request on GitHub +[Opening a Pull Request on GitHub](github-pull-request) ## References 1. “GitHub.com Help Documentation.” GitHub Docs, https://docs.github.com/en. 2. Paul, Kevin. “Python Tutorial Seminar Series - Github.” Project Pythia, YouTube, 12 May 2021, https://www.youtube.com/watch?v=fYkPn0Nttlg. +3. “Resolving a Merge Conflict Using the Command Line.” GitHub Docs, https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line. diff --git a/images/4-gitnewbranch.png b/images/4-gitnewbranch.png index e46944b54..2fcb59285 100644 Binary files a/images/4-gitnewbranch.png and b/images/4-gitnewbranch.png differ diff --git a/images/5-gitcheckout.png b/images/5-gitcheckout.png index d16799320..fa5871a38 100644 Binary files a/images/5-gitcheckout.png and b/images/5-gitcheckout.png differ diff --git a/images/6-samplechange.png b/images/6-samplechange.png index ef6c835eb..82f395a43 100644 Binary files a/images/6-samplechange.png and b/images/6-samplechange.png differ diff --git a/images/6a-gitadd.png b/images/6a-gitadd.png index 27b9ab97c..7bc8c1a1b 100644 Binary files a/images/6a-gitadd.png and b/images/6a-gitadd.png differ diff --git a/images/6b-gitlog.png b/images/6b-gitlog.png index 7e909e81a..3afabd9d8 100644 Binary files a/images/6b-gitlog.png and b/images/6b-gitlog.png differ diff --git a/images/6c-gitpush.png b/images/6c-gitpush.png index ce2881ea0..c42bfefc5 100644 Binary files a/images/6c-gitpush.png and b/images/6c-gitpush.png differ diff --git a/images/6d-setupstream.png b/images/6d-setupstream.png index a6e9cbf66..f69688df5 100644 Binary files a/images/6d-setupstream.png and b/images/6d-setupstream.png differ diff --git a/images/7-github-branchandstatus.png b/images/7-github-branchandstatus.png index 78a29a04d..7f81cc23b 100644 Binary files a/images/7-github-branchandstatus.png and b/images/7-github-branchandstatus.png differ diff --git a/images/PR.png b/images/PR.png deleted file mode 100644 index 220a76f08..000000000 Binary files a/images/PR.png and /dev/null differ diff --git a/images/basicbranch.png b/images/basicbranch.png deleted file mode 100644 index 920ddecd2..000000000 Binary files a/images/basicbranch.png and /dev/null differ diff --git a/images/branching.gif b/images/branching.gif new file mode 100644 index 000000000..31e66bdd0 Binary files /dev/null and b/images/branching.gif differ diff --git a/images/cloning.gif b/images/cloning.gif new file mode 100644 index 000000000..7515ef00b Binary files /dev/null and b/images/cloning.gif differ diff --git a/images/deletingbranch.gif b/images/deletingbranch.gif new file mode 100644 index 000000000..f290dd039 Binary files /dev/null and b/images/deletingbranch.gif differ diff --git a/images/git branching.pptx b/images/git branching.pptx new file mode 100644 index 000000000..26d84fb35 Binary files /dev/null and b/images/git branching.pptx differ diff --git a/images/gitworkflow.gif b/images/gitworkflow.gif new file mode 100644 index 000000000..af453f033 Binary files /dev/null and b/images/gitworkflow.gif differ diff --git a/images/pull.png b/images/pull.png deleted file mode 100644 index 6d15667e2..000000000 Binary files a/images/pull.png and /dev/null differ diff --git a/images/pulling.gif b/images/pulling.gif new file mode 100644 index 000000000..20389de00 Binary files /dev/null and b/images/pulling.gif differ diff --git a/images/pullrequest.gif b/images/pullrequest.gif new file mode 100644 index 000000000..c8cb2cebb Binary files /dev/null and b/images/pullrequest.gif differ diff --git a/images/pushing.gif b/images/pushing.gif new file mode 100644 index 000000000..a09edf5e2 Binary files /dev/null and b/images/pushing.gif differ diff --git a/images/remote.png b/images/remote.png deleted file mode 100644 index ec4a72156..000000000 Binary files a/images/remote.png and /dev/null differ diff --git a/images/remotePR.png b/images/remotePR.png deleted file mode 100644 index fe04298c1..000000000 Binary files a/images/remotePR.png and /dev/null differ diff --git a/images/team.png b/images/team.png deleted file mode 100644 index 57f67b7d0..000000000 Binary files a/images/team.png and /dev/null differ