diff --git a/LICENCE b/LICENCE index caf2c8b..3005366 100644 --- a/LICENCE +++ b/LICENCE @@ -4,10 +4,10 @@ Instructional Material The instructional material in this course is copyright © 2023 University of Exeter and is made available under the Creative Commons Attribution 4.0 International licence (https://creativecommons.org/licenses/by/4.0/). Instructional material -consists of material that is contained within the _episodes and images folders in -this repository, with the exception of code snippets and example programs found -in files within these folders. Such code snippets and example programs are -considered software for the purposes of this licence. +consists of material that is contained within the _episodes, images and downloads +folders in this repository, with the exception of code snippets and example +programs found in files within these folders. Such code snippets and example +programs are considered software for the purposes of this licence. Software diff --git a/_episodes/11_undoing_changes.md b/_episodes/11_undoing_changes.md index 0a7eed9..ee5c618 100644 --- a/_episodes/11_undoing_changes.md +++ b/_episodes/11_undoing_changes.md @@ -227,12 +227,11 @@ In effect, this will 'rewind' the commit history back to finish at the given put all changes since `` in the working tree, giving us a chance to work with the files as they currently are before the reset. -For example, let's create a file `foo.txt` that contains some random -text: +For example, let's create an empty file `foo.txt`. We can do this using +the `touch` command within the root folder of our repository: ``` -Some foo-ey random text - +$ touch foo.txt ``` We'll make a commit of this new file and remove it via a reset. First, we make diff --git a/_episodes/12_ignoring_files.md b/_episodes/12_ignoring_files.md index 1dbacd9..6617485 100644 --- a/_episodes/12_ignoring_files.md +++ b/_episodes/12_ignoring_files.md @@ -259,6 +259,33 @@ Your branch is ahead of 'origin/main' by 2 commits. nothing to commit, working tree clean ``` +Notice how we still have 2 some commits that have not been pushed to the remote +repository. We'll tidy up by pushing these commits, so that our local repository +and remote repository are up-to-date with each other: + +``` +$ git push origin +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +Enumerating objects: 12, done. +Counting objects: 100% (12/12), done. +Delta compression using up to 8 threads +Compressing objects: 100% (7/7), done. +Writing objects: 100% (8/8), 1.11 KiB | 1.11 MiB/s, done. +Total 8 (delta 3), reused 0 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (3/3), completed with 2 local objects. +To https://github.com/jbloggs9999/git-good-practice.git + 92b2ac2..42a9a32 main -> main +``` + +Finally, let's add a note to include some material about ignoring files in our +`TODO.txt` file: + +``` +Add some material about ignoring files + +``` + ## What kind of files should be ignored? diff --git a/_episodes/13_local_branches.md b/_episodes/13_local_branches.md new file mode 100644 index 0000000..9a7c801 --- /dev/null +++ b/_episodes/13_local_branches.md @@ -0,0 +1,347 @@ +--- +layout: page +title: "Working with Local Branches" +order: 13 +session: 2 +length: 25 +toc: true +adapted: true +attrib_name: Version Control with Git - Branching +attrib_link: http://erdavenport.github.io/git-lessons/10-branching.html +attrib_copywrite: Software Carpentry +attrib_license: CC-BY 4.0 +attrib_license_link: https://creativecommons.org/licenses/by/4.0/ +--- + +## Learning objectives + +At the end of this episode you will be able to explain what branches are and how you might use them. +You will also be able to demonstrate how to create an experimental branch and merge it back into the `main` branch. + + +## Repository files + +We've had quite a lot of episodes working on our `git-good-practice` repository. +We've included here copies of the files that we will build on from this episode +onwards. If you haven't been following along with all the examples or exercises, +we suggest updating the files in your repository with the contents of one of +the following archives: + +* As a Zip archive: git-good-practice.zip. + +* As a Tar archive: git-good-practice.tar. + +You should place the archive contents in your own `git-good-practice` repository +(note: make sure to preserve the directory structure: the file +`Commit-good-practice.md` should be placed in the subdirectory +`Good-practice-guides` of the repository root folder). Then commit the changes +to `main` and use `git push` to update your remote repository. + + +## Concept of branches + +Git branches are a core feature of the Git version control system. They allow you to create multiple lines of +development within a single repository, allowing you to work on multiple features or fixes simultaneously, without +affecting the main codebase. + +In simple terms, a branch is a separate series of commits of the codebase that diverges from the main codebase. You can think of +it as a separate timeline of changes that runs in parallel with the main timeline. Each branch contains a copy of the +entire codebase, with its own set of changes. + +![A Git branch]({{ site.url }}/images/branch.svg) + +Git branches are incredibly useful for collaborative development, as they allow multiple developers to work on +different features or fixes simultaneously, without stepping on each other's toes. They also provide a way to +experiment with new features or ideas without affecting the stability of the main codebase. + + +## Working with local branches + +We're going to add some new content to the cheatsheet, doing this in a new, dedicated +branch. The content we'll add will be about using branches, so we'll be recording +what we learn as we go. The material on branches in this episode concerns working +with _local_ branches: branches that are created in our local repository, rather +than remotely on GitHub. The next episode will look at remote branches in more +detail. + + +### Creating branches + +The general way to create a new branch in our local repository is: + +``` +git branch +``` + +where `` is the name of the branch we wish to work on. + +When you create a new branch, you can specify the starting point. By default, if you do not specify a +starting point, Git will create the new branch at the `HEAD` commit. + +The `HEAD` is a reference to the current commit in the branch you are currently working on. It is essentially a pointer +to the tip of the branch you have checked out, which can be moved to any commits in the branch. + +When you create a new branch at the current commit, Git creates a new branch pointer that points to the same commit as +the `HEAD`. This means that the new branch initially has the same code as the current branch, but it is a separate branch +that can be modified independently. + +It can be helpful to have a dual picture in your mind when it comes to branches, +thinking of them both as a series of commits and also a pointer to a particular +commit. + + +> #### Branching off a commit +> +> You can create a new branch at any commit in the repository's history. This can be useful if you want to create a new +> branch based on a specific version of your code, or if you want to experiment with changes from a previous commit +> without affecting the current branch. Here's how you can create a new branch at any commit: +> +> 1. Identify the commit you want to create the branch at: Use the `git log` command to view the commit history of the +> repository and find the commit identifier of the commit you want to create the new branch at. +> 2. Create a new branch: Use the `git branch` command with the commit identifier to create a new branch at that commit: +> +> ``` +> git branch +> ``` +> +> For example, to create a new branch called `experimental-branch` based on a commit with the identifier `abc1234`, you would +> run: +> +> ``` +> git branch experimental-branch abc1234 +> ``` +> +> This creates a new branch called experimental-branch at the specified commit. + +In our example, we create a new branch +off of our most recent commit, called `branches-material`: + +``` +$ git branch branches-material +``` + +This will shortly be the branch in which we add new content to the cheatsheet. + + +### Viewing branches + +We can view all the local branches we have in our local repository by running: + +``` +git branch --list +``` + +(Equivalently, we could use the short form `-l` for `--list`.) + +In our `git-good-practice` repository, this would show us: + +``` +$ git branch --list + branches-material +* main +``` + +The asterisk (\*) preceding "main" is used to indicate the currently checked out branch in your local repository. +Another way to find out which branch you have checked out is to run `git status`. + +> #### `main` is just a branch +> +> The main branch in Git is simply a branch like any other branch in your repository, created automatically +> to hold the initial commit of the repository's history. +> +> Because the main branch is created automatically and is the default branch, it is often used as the primary branch +> for a project's development. However, you can choose to rename the main branch or use a different branch as the +> primary branch if you prefer. + + +### Adding commits to a branch + +In order to work on a branch, we need to **checkout** the branch so that any +new commits we make are added to the branch. The general command for doing this +is: + +``` +git checkout +``` + +> #### Branching off a branch +> +> There is nothing stopping us from creating a new branch that starts on a different +> branch to `main`. For example, suppose you have checked out a branch called `feature-branch`, +> and you want to create a new branch called `bugfix-branch` on top of `feature-branch`. If +> you do not specify a starting point for the new branch, Git will create it at the current commit on +> `feature-branch`, i.e. the commit that `HEAD` is pointing to. + + +We now switch to our new branch `branches-material` so that +our new cheatsheet content will feature in this branch, rather than the branch +`main`: + +``` +$ git checkout branches-material +Switched to branch 'branches-material' +``` + +We're now ready to get to work in the branch `branches-material`. We add the +following content to `Git-cheatsheet.md` on what we just learned about creating +a branch. + +``` + +## Branches + +`git branch ` — Create a new local branch called `` based at the + current commit (i.e. at `HEAD`). + +``` + +We make a commit with the new change: + +``` +$ git add Git-cheatsheet.md + +$ git commit -m "Add entry about creating branches" +[branches-material 8124186] Add entry about creating branches + 1 file changed, 6 insertions(+) +``` + +We next add an entry to our cheatsheet about checking out a branch: + +``` +`git checkout ` — Check out the branch ``, so that new commits + are added to ``. + +``` + +Having committed this change, we now view the log to see our new commits: + +``` +$ git log --oneline -5 +51da8da (HEAD -> branches-material) Add entry about checking out a branch +8124186 Add entry about creating branches +42a9a32 (origin/main, origin/HEAD, main) Ignore TODO list file +0984d2b Add material on basic pathspec usage (directories) +92b2ac2 Create general good practice guides directory +``` + +We can see that the new commits have been added to the branch `branches-material` +and that we are now working on `branches-material` as indicated by +`HEAD -> branches-material`. We can also see that commits to `main` stop at +commit `42a9a32` shown by `origin/main, origin/HEAD, main`. + +We can verify that these new commits are not on the `main` branch by examining +the log of `main` directly. In general, we can run + +``` +git log [options] +``` + +to view the commit history contained in a specific branch ``, where +`[options]` are any optional arguments we want to include e.g `--oneline`. In +our example, we get the following history for the `main` branch: + +``` +$ git log --oneline -5 main +42a9a32 (origin/main, origin/HEAD, main) Ignore TODO list file +0984d2b Add material on basic pathspec usage (directories) +92b2ac2 Create general good practice guides directory +5cf8321 Remove rubbish.txt +d26a698 Add some rubbish to try out 'git rm' +``` + +This confirms that the new commits are not on the `main` branch. + +## Merging branches + +Let's now look at how we can incorporate the changes we've made in the +`branches-material` branch into our `main` branch. In Git parlance, we want +to **merge** the commit history in `branches-material` into the history of +the `main` branch. + +Merging is a way to bring together different streams of development and integrate +them into a cohesive whole. This is the key to using Git for collaboration, as +it allows multiple developers to work on different +aspects of a project simultaneously _and then collate their changes_. + +We do this with the `merge` command: + +``` +git merge +``` + +Here, `` is the name of the branch whose commits we want +to bring _into_ the branch we're currently on. + +![Merging branches]({{ site.url }}/images/merge.svg) + +In our example, we need to merge the branch `branches-material` into `main`. +To do this, we need to checkout the branch we want to merge _into_, i.e. +`main`: + +``` +$ git checkout main +Switched to branch 'main' +Your branch is up to date with 'origin/main'. +``` + +Now we can merge `branches-material` into `main`: + +``` +$ git merge branches-material +Updating 42a9a32..51da8da +Fast-forward + Git-cheatsheet.md | 9 +++++++++ + 1 file changed, 9 insertions(+) +``` + +Let's take another look at the log of `main`: + +``` +$ git log --oneline -5 +51da8da (HEAD -> main, branches-material) Add entry about checking out a branch +8124186 Add entry about creating branches +42a9a32 (origin/main, origin/HEAD) Ignore TODO list file +0984d2b Add material on basic pathspec usage (directories) +92b2ac2 Create general good practice guides directory +``` + +We can see that the commits from `branches-material` have been added to +`main`. In fact, Git has just moved `main` to now point to the same commit +as at the end of the `branches-material`, as seen by the line + +``` +51da8da (HEAD -> main, branches-material) Add entry about checking out a branch +``` + +Our `main` branch now has some commits that have not been pushed to the remote +repository, so we will now rectify that: + +``` +$ git push +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +Enumerating objects: 8, done. +Counting objects: 100% (8/8), done. +Delta compression using up to 8 threads +Compressing objects: 100% (6/6), done. +Writing objects: 100% (6/6), 765 bytes | 255.00 KiB/s, done. +Total 6 (delta 4), reused 0 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (4/4), completed with 2 local objects. +To https://github.com/jbloggs9999/git-good-practice.git + 42a9a32..51da8da main -> main +``` + +### Exercise + +Add another commit to the `branches-material` branch about merging branches. +You may wish to use the following text: + +``` +`git merge ` — Combine the commit history of `` + with that of the branch currently checked out. + +``` + +Once you've done that, bring the changes into `main` by merging the branch +`branches-material` into `main`. Finally, push the new commits on `main` to the +remote repository. diff --git a/_episodes/14_remote_branches_with_github.md b/_episodes/14_remote_branches_with_github.md new file mode 100644 index 0000000..e758418 --- /dev/null +++ b/_episodes/14_remote_branches_with_github.md @@ -0,0 +1,544 @@ +--- +layout: page +title: "Remote Branches with GitHub" +order: 14 +session: 2 +length: 30 +toc: true +adapted: false +--- + + +## Learning objectives + +By the end of this episode you will be able to create remote branches using +GitHub and track these remote branches locally. You will also learn how to +merge remote branches using a Pull Request, as well as how to delete branches +in your local and remote repositories. + + +## Local and remote branches + +Branches can reside in our local repository and/or remote repository, in the +same way that commits can. An **upstream** branch is one which resides in the +remote repository and is tracked locally, meaning the local branch is linked to +the remote branch. Our local repository stores references to any remote branches, +prepending their names with `remotes/origin/` (or simply `origin/`). It should +be noted that these remote branches are not updated automatically - we need to +use `git fetch` to update them. + + +### Viewing branches + +We can list _all_ the branches that our local repository is aware of (both +local branches and remote branches) by using `git branch --all` (or +just `git branch -a`): + +``` +$ git branch -a + branches-material +* main + remotes/origin/HEAD -> origin/main + remotes/origin/main +``` + +There are three branches worth noting here, namely `main` (our local version of +`main`), `remotes/origin/main` (our remote version of `main`) and `branches-material` +(our newly created local branch). We can safely ignore +`remotes/origin/HEAD -> origin/main` for the time being. + +As we have only created `branches-material` locally, it does not have a remote +counterpart, unlike `main`. Using GitHub, we can verify there is no remote branch +called `branches-material`. The necessary steps are as follows: + +- **Step 1** Navigate to your repository on GitHub. + +- **Step 2** Click on _branch(es)_, above the list of files on the left-hand side, + as indicated in the following screenshot: + + ![Viewing branches on GitHub]({{ site.url }}/images/github-view-branches.png) + +- **Step 3** Click on _All branches_, located to the left of the green _New branch_ + button on the right-hand side of the screen — this will display a list of all + the branches in your remote repository. `branches-material` will be missing + from this list. + + +## Working with remote branches + +So far, we've seen how to create a local branch, commit to it and merge it into +another branch (e.g. into `main`). This branch didn't have an upstream branch +in the remote repository. We're now going to look at the case where we +use GitHub to create a branch in the _remote repository_, which we then +bring into our local repository to work with. This approach takes advantage of +useful functionality provided by GitHub, promoting collaborative working. We +will look at an alternative workflow that doesn't rely on the features GitHub +provides in a later episode. + +Now, let's add some material to the cheatsheet relating to working with remote +branches, using GitHub to drive this development. The basic flow for doing this +will be the following: + +* Create a remote branch on GitHub that will receive our additions to the + cheatsheet. + +* Work on the cheatsheet locally, then push the changes up to the remote branch. + +* Use GitHub to merge the work into the `main` branch in the remote repository, + using a Pull Request. + +In order to do this, we need to do the following: + +* Create a remote branch on GitHub. + +* Update our local repository from the remote repository, so that we have a + reference to the newly created remote branch. + +* Create a local branch that is set up to track the remote one. + +* Add new commits to the local branch corresponding to our work on the + cheatsheet. + +* Push these commits to the upstream remote branch. + +* Merge the remote branch into the remote `main` branch, using + a Pull Request on GitHub. + +* Update our local repository to reflect this change to the remote repository. + + +### Create a remote branch on GitHub + +In GitHub, the following steps allow you to create a new remote branch: + +- **Step 1** Navigate to your repository on GitHub. + +- **Step 2** Click on the dropdown, located to the left of _branches_, on the + left-hand side of the screen. + +- **Step 3** Select the branch you would like to create a branch from. (For this + course, this will typically be `main`. If it is `main`, this step + becomes redundant.) + +- **Step 4** Click on the dropdown again and type in the name of your new branch + where it says _Find or create a branch..._. + +- **Step 5** Click on _Create branch: new-branch from 'base-branch'_, where + _new-branch_ is the name of your new branch and _base-branch_ is the name of + the branch you are branching off of (e.g. `main`). + +In our example `git-good-practice` repository, let's suppose we've just created a +new remote branch called `remote-branches-material`, which is based on top of +`main`. Our local repository doesn't have any knowledge of this new branch, as +can be seen by listing the branches: + +``` +$ git branch -a + branches-material +* main + remotes/origin/HEAD -> origin/main + remotes/origin/main +``` + + +### Fetch the remote branch + +In order to update our local repository so that it has knowledge of the new +remote branch, we use the following command from within our local repository: + +``` +git fetch +``` + +(Like with `git push` and `git pull`, we can instead run `git fetch origin` to +be explicit about the reference to the remote repository.) +We won't go into too much detail about exactly what `git fetch origin` is doing. For +our purposes, we use it to inspect the remote repository for information about +any new branches, or commits that have been made in remote branches, that our +local repository doesn't yet know about. + +In our example, after running `git fetch` in our `git-good-practice` +repository, we see that information about the new remote `remote-branches-material` +has been retrieved: + +``` +$ git fetch +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +From https://github.com/jbloggs9999/git-good-practice + * [new branch] remote-branches-material -> origin/remote-branches-material + +$ git branch -a + branches-material +* main + remotes/origin/HEAD -> origin/main + remotes/origin/main + remotes/origin/remote-branches-material +``` + +However, this has only created a reference to the remote branch, indicated +by `remotes/origin/remote-branches-material` in the above output. We still need +to create a _local_ branch that will track the remote branch. + + +### Create a new tracking local branch + +In order to create a local version of the +`origin/remote-branches-material` branch where we can add commits, we can +perform the following checkout: + +``` +$ git checkout remote-branches-material +Switched to a new branch 'remote-branches-material' +branch 'remote-branches-material' set up to track 'origin/remote-branches-material'. +``` + +You may be surprised by this: after all, we've asked Git to checkout a branch +that doesn't actually exist! Fortunately, Git is smart enough to realise that +what we want to do is set up a new local branch that tracks the `origin/remote-branches-material` +remote branch. So it automatically creates a new local branch — called `remote-branches-material` — that +will track `origin/remote-branches-material`, and checks out this new local branch for us. We +can verify this by listing all the branches again: + +``` +$ git branch -a + branches-material + main +* remote-branches-material + remotes/origin/HEAD -> origin/main + remotes/origin/main + remotes/origin/remote-branches-material +``` + +### Add content to the local branch and push + +We are now set to add our new material to `Git-cheatsheet.md` about remote +branches. We modify the start of the subsection _Branches_ so that it now reads as +follows: + +``` +## Branches + +`git branch ` — Create a new branch called `` + based at the current commit (i.e. at `HEAD`). + +`git checkout ` — Check out the branch ``, so that new commits + are added to ``. + +- Can also be used to create and checkout a new local branch `` that + tracks an existing remote branch `origin/`. + +`git merge ` — Combine the commit history of `` + with that of the branch currently checked out. +``` + +Having included this addition, we commit to our local `remote-branches-material` branch. + + +> #### Markdown syntax +> +> Unordered lists are denoted by using a hyphen (`-`) or an asterisk (`*`), +> followed by a space, with the text in the list item following. Example: +> +> ``` +> - Foo +> - Bar +> - Baz +> ``` +> renders as: +> - Foo +> - Bar +> - Baz +> +> Text that flows over multiple lines in the source file, yet belongs to a single +> list item, should respect the indenting. For example: +> +> ``` +> * list entry with +> +> new line +> +> * the quick brown fox jumps over the +> lazy dog +> ``` +> +> renders as: +> +> * list entry with +> +> new line +> +> * the quick brown fox jumps over the +> lazy dog + +We're now in the position where our local branch +`remote-branches-material` is ahead of the remote branch +`origin/remote-branches-material` that it tracks, as can be seen from +the log on `remote-branches-material`: + +``` +$ git log --oneline -3 +5125372 (HEAD -> remote-branches-material) Add note about creating local tracking branches +3b918f2 (origin/remote-branches-material, origin/main, origin/HEAD, main, branches-material) Add entry about merging branches +51da8da Add entry about checking out a branch +``` + +In order to update an upstream remote branch with new commits in the local +tracking branch, we can use `git push` (or `git push origin`), like we did when working with +the `main` branch in the episode +[Pushing to and Pulling From the Remote Repository]({{ site.url }}/10_pushing_and_pulling/index.html). +Note however that this will push the commits _on the currently checked out branch_ to its upstream +remote branch. So, in general, if you have a local branch `` that tracks a +remote branch `origin/`, then in order to push `` to `origin/` we +need to first checkout ``. + + +> #### Alternative: specify the branch explicitly +> +> Alternatively, if you have a local branch `` that tracks a remote branch +> `origin/`, then you can run `git push origin ` from any local branch +> to push commits from `` to `origin/`. + + +In our example, we're already on the branch `remote-branches-material` that we want to push, +so we can just go ahead and do `git push`: + +``` +$ git push +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +Enumerating objects: 5, done. +Counting objects: 100% (5/5), done. +Delta compression using up to 8 threads +Compressing objects: 100% (3/3), done. +Writing objects: 100% (3/3), 438 bytes | 219.00 KiB/s, done. +Total 3 (delta 2), reused 0 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (2/2), completed with 2 local objects. +To https://github.com/jbloggs9999/git-good-practice.git + 3b918f2..5125372 remote-branches-material -> remote-branches-material +``` + +The last line of the `git push` message shows that we've successfully updated the remote +branch with the new commit. + + +## Merge remote branch into remote `main` + +Once we have pushed our changes to the remote branch, we can merge said remote +branch into remote `main` by means of a Pull Request on GitHub. We can create and +complete a Pull Request (PR) as follows: + +- **Step 1** Navigate to your repository on GitHub. + +- **Step 2** Click on the _Pull requests_ tab (third tab from the left). + +- **Step 3** Click on the green _New pull request_ button on the right-hand side + of the screen. + +- **Step 4** Ensure `main` has been chosen as _base_ and choose your remote branch, + which in this case is `remote-branches-material`, as _compare_. + +- **Step 5** Click on the green _Create pull request_ button. + +- **Step 6** GitHub will generate a title based on the name of the branch you + are comparing, but this can be changed. You are also welcome to add a + description where it says _Leave a comment_. + +- **Step 7** Click on the green _Create pull request_ button. + +- **Step 8** Click on the green _Merge pull request_ button, located near the + bottom of the page. + + +## Pull changes into our local repository + +We have just merged our branch into `main` in the remote repository. To see +the changes made to `main` in our local repository, we need to pull them from +the remote repository. + +To update `main`, we first check it out: + +``` +$ git checkout main +Switched to branch 'main' +Your branch is up to date with 'origin/main'. +``` + +There's an important point to make about the output here. It is stated that +`Your branch is up to date with 'origin/main'.`. This doesn't mean there aren't changes on the remote to +pull in. Instead, it means that Git is not aware of any extra commits in +`origin/main` compared to `main` _since last `fetch`ing from the remote repository_. + +So, let us fetch updates from the remote repository: + +``` +$ git fetch +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +remote: Enumerating objects: 1, done. +remote: Counting objects: 100% (1/1), done. +remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 +Unpacking objects: 100% (1/1), 667 bytes | 83.00 KiB/s, done. +From https://github.com/jbloggs/git-good-practice + 3b918f2..86ebbee main -> origin/main +``` + +We can see that our local repository is now aware of the change to the remote +`origin/main` branch by checking the status again: + +``` +$ git status +On branch main +Your branch is behind 'origin/main' by 2 commits, and can be fast-forwarded. + (use "git pull" to update your local branch) + +nothing to commit, working tree clean +``` + +In the +[Pushing to and Pulling From the Remote Repository]({{ site.url }}/10_pushing_and_pulling/index.html) +episode, we mentioned that `git pull` can be used to retrieve updates from the +remote repository. To be more precise, `git pull` is used to bring in commits +_in a remote branch into a corresponding local branch_. In general, if you have +a remote branch that has commits not yet in a local tracking +branch ``, then run the following command _with `` checked out_ +to update `` with these new commits: + +``` +git pull +``` + +(or, to be explicit about the remote repository, `git pull origin`). + +> #### `pull` automatically `fetch`es +> +> `git pull` actually performs a two step process on a branch +> ``. First, it runs a `git fetch` to retrieve all new commits, +> branches, etc. from the remote repository. Then, +> it merges the changes that have been fetched into the `origin/` into +> ``. As a result, we did not in fact need to use the `git fetch` command +> before using `git pull` above. + +We pull the changes to `origin/main` into our local `main` branch: + +``` +$ git pull +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +Updating 3b918f2..86ebbee +Fast-forward + Git-cheatsheet.md | 3 +++ + 1 file changed, 3 insertions(+) +``` + +We can now see from the log that our changes are fully reflected in `main`: + +``` +$ git log --oneline -5 +86ebbee (HEAD -> main, origin/main, origin/HEAD) Merge pull request #1 from jbloggs9999/remote-branches-material +5125372 (origin/remote-branches-material, remote-branches-material) Add note about creating local tracking branches +3b918f2 (branches-material) Add entry about merging branches +51da8da Add entry about checking out a branch +8124186 Add entry about creating branches +``` + +## Cleaning up + +All the work we've done in our branches has been incorporated into `main` (both +locally and in the remote repository). So, to clean up the state of the repository, +we going to delete the branches `branches-material` and `remote-branches-material`, +including the remote version of `remote-branches-material`, since these +no longer serve any purpose. + + +> ### Good practice: deleting old branches +> +> It is good practice to delete branches that are no longer required. This makes +> navigating a repository easier and makes it clear what work is still ongoing +> compared to work that has been finished. + + +### Deleting branches from a local repository + +The general commands for deleting branches are as follows: + +* For deleting _local_ branches: `git branch -d ` + +* For deleting _remote_ branches: `git branch -d -r ` + +In both cases, note that you can specify more than one branch by separating the +branch names by a space. + +There are a couple of important things to note about deleting branches: + +* You can't delete a branch you currently have checked out. So make sure you + checkout a different branch before deletion e.g. do deletions from `main`. + +* Deleting branches removes the commits contained in those branches which don't + feature in other branches. So, before deleting a branch, be sure that the + changes you want to keep have been merged into another branch e.g. `main`. + +We delete our local branches: + +``` +$ git branch -d branches-material remote-branches-material +Deleted branch branches-material (was 3b918f2). +Deleted branch remote-branches-material (was 5125372). +``` + +Then we delete our remote branch reference `origin/remote-branches-material`: + +``` +$ git branch -r -d origin/remote-branches-material +Deleted remote-tracking branch origin/remote-branches-material (was 5125372). +``` + +> ### Force deletion +> +> Git may stop you from deleting a branch, because it can't verify that +> all the commits in the branch have been merged into a corresponding remote +> branch or another local branch. This is a protection +> mechanism to stop you from potentially losing changes. If you encounter this but +> are sure you want to proceed with the deletion, you can force the deletion +> by using `-D` instead of `-d` in the commands above. + + +Our local repository is now looking cleaner with regards to the branches we have: + +``` +$ git branch -a +* main + remotes/origin/HEAD -> origin/main + remotes/origin/main +``` + +Note also that the references to the non-`main` branches have disappeared from +the log (note that the _commits_ have _not_ disappeared, however, because these +are part of `main`): + +``` +$ git log --oneline -5 +86ebbee (HEAD -> main, origin/main, origin/HEAD) Merge pull request #1 from jbloggs9999/remote-branches-material +5125372 Add note about creating local tracking branches +3b918f2 Add entry about merging branches +51da8da Add entry about checking out a branch +8124186 Add entry about creating branches +``` + + +### Deleting branches from the remote repository via GitHub + +Finally, we need to delete the remote branch `remote-branches-material` from the +remote repository in GitHub. The necessary steps are as follows: + +- **Step 1** Navigate to your respository on GitHub. + +- **Step 2** Click on _branches_, above the list of files on the left-hand side. + +- **Step 3** Click on _All branches_, located to the left of the green _New branch_ + button on the right-hand side of the screen. + +- **Step 4** Identify the branch to be deleted and click on the appropriate + _bin icon_ on the right-hand side of the screen. If you hover over the icon, + it will show a message stating _Delete chosen-branch_, where _chosen-branch_ + is the name of the branch to be deleted. diff --git a/_episodes/15_collaborating_with_branches.md b/_episodes/15_collaborating_with_branches.md new file mode 100644 index 0000000..bb91595 --- /dev/null +++ b/_episodes/15_collaborating_with_branches.md @@ -0,0 +1,653 @@ +--- +layout: page +title: "Collaborating with Branches" +order: 15 +session: 2 +length: 45 +toc: true +adapted: false +--- + +## Learning objectives + +By the end of this episode you will have learned about a simple strategy +for using branches to collaborate with others on a shared codebase, called +feature branching. You will also have worked through an example of how this +strategy works in practice. + + +## Collaborating with others + +So far, we've only been using Git and GitHub as a solo developer. But the real +power of version control systems is realised when collaborating with other +developers on a shared project. Branching in Git provides the means for multiple +people in a way that allows them to work concurrently and bring their work together +in a controlled, transparent way. If you're using GitHub to host your remote +repository, then Pull Requests provide a way to communicate to others about +your changes. + +The key thing to remember when collaborating with Git is that, while there may +only be a single remote repository, _every developer has their own local repository_ that +is linked to the remote repository. The corollary to this is: + +* each developer is responsible for pushing the work from their local repository + to the remote one; and + +* each developer needs to pull in work that others have contributed to the + remote repository into their local repository. + +It's important that this is done promptly and regularly so that any changes +are not missed by you or others. + +There are different strategies and philosophies on how branches can be used +for collaboration. For this course, we're going to discuss a simple strategy +called _feature branching_. + + +## Feature branching + +A **feature** in this context is any piece of work that adds to of the +software's overall development, whether this be a new piece of functionality, a +bug fix, some documentation, etc. In feature branching, new features are +developed in their own, dedicated **feature branches** that branch off the +`main` branch. When the feature is ready to be shared with others, the feature +branch is merged back into `main`. + +The `main` branch and feature branches take on different roles: + +* **The `main` branch**: This includes code changes that you want to share with + each other, or that are ready for release into the world. You should consider + it the 'neat' version of your work. As a general rule, _code only makes it into + `main` through merging a feature branch. You don't commit directly to `main`._ + +* **Feature branches**: These are branches where you work on code to develop + features, so will contain 'work in progress' until they're ready to merge + back into `main`. + +A common scenario you will come across when working on a feature branch is +where `main` gets updated through someone else merging a feature branch they're +working on. When it comes to you merging your feature branch into `main`, the +golden rule is to make sure you merge any changes to `main` _into_ your +feature branch _before_ merging your feature branch into `main`. This ensures +you are adding your work to the latest version of the 'common' codebase and +resolve any issues in your feature branch: + +* It gives you a chance to check that the changes you are making are consistent + with other peoples' work, which may have passed under the radar when merging. + +* It also gives you a chance to resolve any _merge conflicts_ that may arise + when you try to merge your work into the common codebase (about which more in + a later episode). + + +### Creating feature branches + +We will be creating feature branches using the workflow described in the previous +episode, [Remote Branches with GitHub]({{ site.url }}/14_remote_branches_with_github/index.html): +feature branches will be created remotely on GitHub and then fetched in for us +to work on locally. + + +### Protocol for merging feature branches into `main` + +Below we give steps for merging a feature branch `foo-feature` into `main`. We +assume `foo-feature` exists both as a remote branch in the remote repository and +also a local tracking branch in our local repository. + +1. Create a Pull Request on GitHub corresponding to the merge of `foo-feature` + into `main`. + +2. Pull any changes to `main` on the remote repository into your local version + of `main` (using `git pull` on your local `main` branch). + + a) If `main` was unchanged by the pull then go to step 2, + otherwise go to step b) below. + + b) If `main` got updated by the pull, then merge `main` into `foo-feature` + in your local repository before continuing, by using `git merge`. + If there are merge conflicts, these MUST be resolved and the merge into + `foo-feature` completed before continuing to step c) below. Take the + opportunity to make sure this merge hasn't introduced any problems into + the codebase (e.g. inconsistencies in naming, etc.) + + c) Pull the remote `main` into your local `main` again to be + sure no further changes were made while you were performing the merge in + step b). If the branch wasn't updated then proceed + to step 2 below, otherwise curse your luck and go back to step b). + +2. Push the commits in your local `foo-feature` branch to the corresponding + remote branch. + +3. Complete the Pull Request on GitHub to merge the `foo-feature` branch + into `main` on the remote. + +4. Pull the changes to `main` from the remote repository into your local repository. + Optional, but recommended: delete the feature branch `foo-feature` from GitHub + and from your remote repository (including the reference `origin/foo-feature` + to the remote branch). + + +## Example: Joe Bloggs and Jane Doe + +We're now going to assume that Joe Bloggs and Jane Doe are two people collaborating +on the `git-good-practice` repository. They will work with the same +remote repository, created under Joe's account, but will each have their own +associated local repositories. They're going to use the _feature branch_ +strategy, discussed in the previous section, to add: + +* Material to the cheatsheet about fetching remote branches from a remote + repository. + +* A new file documenting good practice when collaborating together. + + +In order for two people to work on the same remote repository on GitHub, they +each need to be listed as collaborators on the repository. + +> ### Collaborators on a GitHub repository +> +> If you are the owner of a repository on GitHub, you can invite collaborators +> to work on the repository using the +> instructions in the GitHub documentation. + + +### Exercise + +At this point in the course, we encourage participants to pair up and work +together on a common repository, taking the roles of Joe and Jane. + +So, find a partner to work with. Have one of you invite the other as a collaborator +on your repository. The collaborator should then clone the other person's +repository using the above instructions, so that you are both working on a +common remote repository. In what follows, one of you should play the role of +Joe Bloggs and the other of Jane Doe. + + +> #### Solo work +> +> If you are working through these course notes by yourself then try imagining +> you are two different developers collaborating on the repository together. We +> suggest you clone a fresh copy of the remote repository to a new local repository +> on your computer, while keeping your original local repository. This will +> help you simulate the scenario of collaborators each having their own local +> repository. + + +## Creating the branches + +Joe and Jane begin by creating remote branches on GitHub for their work, creating +these at the same time: + +* **Joe** creates a remote branch called `fetching-material`, which will contain + material about fetching from a remote repository. + +* **Jane** creates a remote branch called `collaboration-good-practice`, which + will contain work on good practice while collaborating. + +Next, Joe and Jane need to each create a local branch +that will track their remote branch. + +### Joe's local branch + +Joe fetches references to the new branches in the remote repository, then +creates a new local branch to track his remote `fetching-material` branch (and +also checks out this new local branch): + +``` +$ git fetch +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +From https://github.com/jbloggs9999/git-good-practice + * [new branch] collaboration-good-practice -> origin/collaboration-good-practice + * [new branch] fetching-material -> origin/fetching-material + +$ git checkout fetching-material +Switched to a new branch 'fetching-material' +branch 'fetching-material' set up to track 'origin/fetching-material'. +``` + +Notice that the fetch creates references to _both_ of the new remote branches, +`fetching-material` and `collaboration-good-practice`, which Joe and Jane created on +GitHub a moment ago. In contrast, Joe only has a local branch corresponding +to his remote `fetching-material` branch, since this is the branch he performed +the `git checkout` on: + +``` +$ git branch -a +* fetching-material + main + remotes/origin/HEAD -> origin/main + remotes/origin/collaboration-good-practice + remotes/origin/fetching-material + remotes/origin/main +``` + +### Jane's local branch + +Jane runs the analogous commands in her local repository, in this case creating +a local tracking branch for her `collaboration-good-practice` remote branch +instead: + +``` +$ git fetch +Username for 'https://github.com': janedoe9999 +Password for 'https://janedoe9999@github.com': +From https://github.com/jbloggs9999/git-good-practice + * [new branch] collaboration-good-practice -> origin/collaboration-good-practice + * [new branch] fetching-material -> origin/fetching-material + +$ git checkout collaboration-good-practice +Switched to a new branch 'collaboration-good-practice' +branch 'collaboration-good-practice' set up to track 'origin/collaboration-good-practice'. + +$ git branch -a +* collaboration-good-practice + main + remotes/origin/HEAD -> origin/main + remotes/origin/collaboration-good-practice + remotes/origin/fetching-material + remotes/origin/main +``` + +## Working on the feature branches + +### Joe's `fetching-material` feature branch + +Joe adds the following content to `Git-cheatsheet.md`: + +``` + +## Syncing with a remote repository + +`git fetch origin` — Retrieve references to new remote branches, and/or commits + that are contained in remote branches, from the remote + repository (referred to as `origin`). + +``` + +He then commits it on his (local) `fetching-material` branch: + +``` +$ git add Git-cheatsheet.md + +$ git commit -m "Add entry about fetching from a remote" +[fetching-material 1d026a8] Add entry about fetching from a remote + 1 file changed, 7 insertions(+) +``` + +Checking the status, Joe confirms that his local `fetching-material` branch is 1 commit +ahead of the associated remote branch: + +``` +$ git status +On branch fetching-material +Your branch is ahead of 'origin/fetching-material' by 1 commit. + (use "git push" to publish your local commits) + +nothing to commit, working tree clean +``` + +In order to back up his work and give Jane a preview of what he's been doing, +Joe pushes the changes to his local `fetching-material` branch to the remote +`origin/fetching-material`: + +``` +$ git push +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +Enumerating objects: 5, done. +Counting objects: 100% (5/5), done. +Delta compression using up to 8 threads +Compressing objects: 100% (3/3), done. +Writing objects: 100% (3/3), 494 bytes | 123.00 KiB/s, done. +Total 3 (delta 2), reused 0 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (2/2), completed with 2 local objects. +To https://github.com/jbloggs9999/git-good-practice.git + 86ebbee..1d026a8 fetching-material -> fetching-material +``` + +The history on Joe's `fetching-material` branch now looks like this: + +``` +$ git log --oneline -5 +1d026a8 (HEAD -> fetching-material, origin/fetching-material) Add entry about fetching from a remote +86ebbee (origin/main, origin/collaboration-good-practice, origin/HEAD, main) Merge pull request #1 from jbloggs9999/remote-branches-material +5125372 Add note about creating local tracking branches +3b918f2 Add entry about merging branches +51da8da Add entry about checking out a branch +``` + + +### Jane Doe and her `collaboration-good-practice` feature branch + +Jane creates a new file called `Collaboration-good-practice.md` in the +`Good-practice-guides` directory (which she includes as a stand-alone commit) +and adds the following content about the above feature branch strategy: + +``` +# Best practice for collaboration + +## A basic feature branch strategy + +A basic way to collaborate on a common repository is to use *feature branching*. +A *feature* in this context is any piece of work that adds to of the +software's overall development, whether this be a new piece of functionality, a +bug fix, some documentation, etc. In feature branching, new features are +developed in their own, dedicated *feature branches* that branch off the +`main` branch. When the feature is ready to be shared with others, the feature +branch is merged back into `main`. + +``` + +Like Joe, she then also pushes the new commits on her local +`collaboration-good-practice` to the associated remote branch, +`origin/collaboration-good-practice`: + +``` +$ git push origin +Username for 'https://github.com': janedoe9999 +Password for 'https://janedoe9999@github.com': +Enumerating objects: 10, done. +Counting objects: 100% (10/10), done. +Delta compression using up to 8 threads +Compressing objects: 100% (7/7), done. +Writing objects: 100% (8/8), 1.04 KiB | 353.00 KiB/s, done. +Total 8 (delta 2), reused 1 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (2/2), completed with 1 local object. +To https://github.com/jbloggs9999/git-good-practice.git + 86ebbee..b9df491 collaboration-good-practice -> collaboration-good-practice +``` + +Having done this, her `collaboration-good-practice` history looks as follows: + +``` +$ git log --oneline -5 +b9df491 (HEAD -> collaboration-good-practice, origin/collaboration-good-practice) Add material on feature branching +687cf02 Start good practice guide on collaboration +86ebbee (origin/main, origin/fetching-material, origin/HEAD, main) Merge pull request #1 from jbloggs9999/remote-branches-material +5125372 Add note about creating local tracking branches +3b918f2 Add entry about merging branches +``` + + +Let us take a moment to point out that, at this point, `origin/fetching-material` +hasn't been updated in Jane's local repository, and neither has +`origin/collaboration-good-practice` been updated in Joe's local repository. +This is because they haven't yet fetched updates to the corresponding remote +branches from the remote repository. This underlines the +fact that the information about remote branches only +gets updated in local repositories when you tell Git to retrieve updates from +the remote, via `git fetch` or `git pull`. + + +## Merging + +## First to the pass: Joe + +Joe finishes his work before Jane does and so gets to work on merging his +feature branch into the `main` branch. Following the strategy that was discussed +in the episode [Remote Branches with GitHub]({{ site.url }}/14_remote_branches_with_github/index.html), +he creates a Pull Request associated to the merge. + +Having done this, he checks that Jane hasn't +merged any work into the remote `main` branch. He could do this by examining +the history of `main` on GitHub, or by checking out `main` and +pulling in any changes from the remote: + +``` +$ git checkout main +Switched to branch 'main' +Your branch is up to date with 'origin/main'. + +$ git pull +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +remote: Enumerating objects: 10, done. +remote: Counting objects: 100% (10/10), done. +remote: Compressing objects: 100% (5/5), done. +remote: Total 8 (delta 2), reused 8 (delta 2), pack-reused 0 +Unpacking objects: 100% (8/8), 1.02 KiB | 17.00 KiB/s, done. +From https://github.com/jbloggs9999/git-good-practice + 86ebbee..b9df491 collaboration-good-practice -> origin/collaboration-good-practice +Already up to date. +``` + +Recall that `Your branch is up to date with 'origin/main'.` after the +checkout in the above output only means that Git is not aware of any extra commits in +`origin/main` compared to `main` since the last `fetch` or `pull`. In this +case, the `git pull` command confirms that the local `main` branch was already up to date with +the remote repository's `main` branch. It also shows that then new commits in the +`origin/collaboration-good-practice` that Jane's working on have been fetched. + +Since his `main` branch is fully up to date with +the remote version, Joe goes ahead and performs the merge of his feature branch +into `main` on GitHub, by completing the Pull Request. He then updates his local +`main` branch with the merged changes: + +``` +$ git pull +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +remote: Enumerating objects: 1, done. +remote: Counting objects: 100% (1/1), done. +remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 +Unpacking objects: 100% (1/1), 654 bytes | 93.00 KiB/s, done. +From https://github.com/jbloggs9999/git-good-practice + 86ebbee..4e209e9 main -> origin/main +Updating 86ebbee..4e209e9 +Fast-forward + Git-cheatsheet.md | 7 +++++++ + 1 file changed, 7 insertions(+) +``` + + +### Jane: merging after changes to `main` + +Jane is ready to merge her `collaboration-good-practice` feature branch into +`main`, so she create a Pull Request linked to the remote feature branch. + +As the feature branch protocol recommends, she checks to see whether her local +`main` branch is up-to-date with the remote repository: + +``` +$ git checkout main +Switched to branch 'main' +Your branch is up to date with 'origin/main'. + +$ git pull origin +Username for 'https://github.com': janedoe9999 +Password for 'https://janedoe9999@github.com': +remote: Enumerating objects: 4, done. +remote: Counting objects: 100% (4/4), done. +remote: Compressing objects: 100% (2/2), done. +remote: Total 4 (delta 3), reused 2 (delta 2), pack-reused 0 +Unpacking objects: 100% (4/4), 974 bytes | 27.00 KiB/s, done. +From https://github.com/jbloggs9999/git-good-practice + 86ebbee..4e209e9 main -> origin/main + 86ebbee..1d026a8 fetching-material -> origin/fetching-material +Updating 86ebbee..4e209e9 +Fast-forward + Git-cheatsheet.md | 7 +++++++ + 1 file changed, 7 insertions(+) +``` + +(Again, she could also have done this by looking at the history of `main` on +GitHub.) Jane finds that there have been changes made to the `main` branch while +she was working on her feature branch, as indicated by the line + +``` + 86ebbee..4e209e9 main -> origin/main +``` + +Therefore, she merges her now updated `main` branch into her feature branch, to +ensure her feature branch includes the latest changes. (Note that she does +this _locally_, rather than on GitHub.) + +``` +$ git checkout collaboration-good-practice +Switched to branch 'collaboration-good-practice' +Your branch is up to date with 'origin/collaboration-good-practice'. + +$ git merge main +Merge made by the 'ort' strategy. + Git-cheatsheet.md | 7 +++++++ + 1 file changed, 7 insertions(+) +``` + +She also then pushes her updated feature branch to the +remote repository, so that her local and remote branches are synchronised. + +``` +$ git push +Username for 'https://github.com': janedoe9999 +Password for 'https://janedoe9999@github.com': +Enumerating objects: 4, done. +Counting objects: 100% (4/4), done. +Delta compression using up to 8 threads +Compressing objects: 100% (2/2), done. +Writing objects: 100% (2/2), 325 bytes | 325.00 KiB/s, done. +Total 2 (delta 1), reused 0 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (1/1), completed with 1 local object. +To https://github.com/jbloggs9999/git-good-practice.git + b9df491..ee1617c collaboration-good-practice -> collaboration-good-practice +``` + +Having done this, she now effectively starts the protocol for merging a feature +branch into `main` again. First she checks there haven't been any further updates +to `main`: + +``` +$ git checkout main +Switched to branch 'main' +Your branch is up to date with 'origin/main'. + +$ git pull +Username for 'https://github.com': janedoe9999 +Password for 'https://janedoe9999@github.com': +Already up to date. +``` + +Having seen there are no further updates, she goes to GitHub and completes +the associated Pull Request, thus merging her remote +`collaboration-good-practice` feature branch into `main` in the remote +repository. Then she pulls down the new, merged changes from `origin/main` into +her local `main` branch: + +``` +$ git pull +Username for 'https://github.com': janedoe9999 +Password for 'https://janedoe9999@github.com': +remote: Enumerating objects: 1, done. +remote: Counting objects: 100% (1/1), done. +remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 +Unpacking objects: 100% (1/1), 648 bytes | 108.00 KiB/s, done. +From https://github.com/jbloggs9999/git-good-practice + 4e209e9..785f6f8 main -> origin/main +Updating 4e209e9..785f6f8 +Fast-forward + Good-practice-guides/Collaboration-good-practice.md | 11 +++++++++++ + 1 file changed, 11 insertions(+) + create mode 100644 Good-practice-guides/Collaboration-good-practice.md +``` + +## Finishing up + +The merged changes added to `main` by Jane won't feature in Joe's local +repository until he pulls them into his local `main` branch. Having seen on +GitHub that Jane has completed her Pull Request, he duly makes sure his local +repository has these changes (making sure he's on `main` to begin with): + +``` +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +nothing to commit, working tree clean + +$ git pull +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +remote: Enumerating objects: 5, done. +remote: Counting objects: 100% (5/5), done. +remote: Compressing objects: 100% (2/2), done. +remote: Total 3 (delta 2), reused 1 (delta 1), pack-reused 0 +Unpacking objects: 100% (3/3), 829 bytes | 48.00 KiB/s, done. +From https://github.com/jbloggs9999/git-good-practice + 4e209e9..785f6f8 main -> origin/main + b9df491..ee1617c collaboration-good-practice -> origin/collaboration-good-practice +Updating 4e209e9..785f6f8 +Fast-forward + Good-practice-guides/Collaboration-good-practice.md | 11 +++++++++++ + 1 file changed, 11 insertions(+) + create mode 100644 Good-practice-guides/Collaboration-good-practice.md +``` + +Both Joe and Jane now have completely up-to-date local repositories. At this point, +they could delete their feature branches, both from the local repository and +the remote repository. + + +## Viewing a graph of history + +Feeling satisfied about a successful collaboration, Joe and Jane decide to take +a look at what they've just accomplished. One nice way to view history in the +repository when multiple branches are involved is to use the `--graph` option with `git log`. +This will pictorially represent the inter-relationships of the branches that +are involved in the commit history: + +``` +git log [options] --graph +``` + +Note: you may find it clearest to use this with the `--oneline` option. + +From within Joe's repository, the output of the graph looks like the following +(viewing only the last 7 commits): + + + +![Git log as a graph]({{ site.url }}/images/git-log-as-graph.png) + +Let's go through this output in more detail: + +* The commit `86ebbee` ("Merge pull request #1 ...") is where Joe and Jane + started their work. + +* The vertical line represents the `main` branch, that we're currently on. After + the starting commit, there are two more commits, `4e209e9` and `785f6f8`, that + show where the feature branches where merged into `main` on the remote. + +* We can see the commit on Joe's feature branch by following the purple line: + the commit is `1d026a8`, where `origin/fetching-material` currently points. (It's + also where the local branch `fetching-material` points, which we see because we + are viewing Joe's local repository.) The feature branch got merged into main + at commit `4e209e9` ("Merge pull request #2 from jbloggs9999/fetching-material") + +* Jane's feature branch commits start at `687cf02` ("Start good practice guide on + collaboration") and continue along the yellow line. Note that commit + `ee1617c` (where `origin/collaboration-good-practice` currently points) is + where Jane merged her `main` branch into `collaboration-good-practice` locally, + after pulling in Joe's merged changes to `main`. Note also the red line connecting + `main` to this commit, indicating Jane's merge. + +* Finally, the latest commit `785f6f8` ("Merge pull request #3 from jbloggs9999/collaboration-good-practice") + is the commit where Jane's feature branch got merged into main on the remote. diff --git a/downloads/episode-13-start/git-good-practice.tar b/downloads/episode-13-start/git-good-practice.tar new file mode 100644 index 0000000..2ee8e05 Binary files /dev/null and b/downloads/episode-13-start/git-good-practice.tar differ diff --git a/downloads/episode-13-start/git-good-practice.zip b/downloads/episode-13-start/git-good-practice.zip new file mode 100644 index 0000000..debb75d Binary files /dev/null and b/downloads/episode-13-start/git-good-practice.zip differ diff --git a/images/branch.svg b/images/branch.svg new file mode 100644 index 0000000..5a8cc4e --- /dev/null +++ b/images/branch.svg @@ -0,0 +1,4 @@ + + + +
main
main
new-branch
new-branch
Text is not SVG - cannot display
\ No newline at end of file diff --git a/images/git-log-as-graph.png b/images/git-log-as-graph.png new file mode 100644 index 0000000..2fdae56 Binary files /dev/null and b/images/git-log-as-graph.png differ diff --git a/images/github-view-branches.png b/images/github-view-branches.png new file mode 100644 index 0000000..6bc58e7 Binary files /dev/null and b/images/github-view-branches.png differ diff --git a/images/merge.svg b/images/merge.svg new file mode 100644 index 0000000..fbdb186 --- /dev/null +++ b/images/merge.svg @@ -0,0 +1,4 @@ + + + +
main
main
main
main
branch-to-merge-in
branch-to-merge-in
branch-to-merge-in
branch-to-merge-in
Merge
Merge
Text is not SVG - cannot display
\ No newline at end of file