Lesson Weekend

When we work on a development project as a collaborator, we have commit privileges to the master repository on GitHub. The development workflow for collaborators in a team takes advantage of Git functionality we don't often use on pair projects: Branching and merging.

Below is an outline of this workflow. Use this lesson as a reference when working on the group project this week:

Git Team Workflow

1. Setup GitHub Repo

First we need a GitHub repository to house our project.

  • Create a repo on GitHub and add all team members as collaborators, as explained in the Git With Collaborators: Setup lesson.

  • Clone the GitHub repository to each pair's computer using $ git clone <repo-url>.

  • Each pair navigates to the cloned project using $ cd <project-directory-name>.

2. Create Branches

Next we make separate feature branches, so pairs can work simultaneously without interfering with one another's code.

  • Each pair creates (and switches to) their own local feature branch by running $ git checkout -b <branch-name>. Each branch should have a different name.

Tips: Keep in mind that repos come with a master branch by default, so we do not need to create one. And if we're ever uncertain which branch we're on, simply run $ git branch.

3. Code

Pairs each complete work on dedicated branches, adding and committing as usual.

4. Pull Origin Master into Local Master

AKA Retrieve Updated Master Code

When our local feature branch contains work we're ready to add to the final version of the project (the master branch), we can begin ensuring new code works with existing master code.

We must first pull any new code teammates may have added to the GitHub master branch (AKA origin master or remote master) into our local master branch, so we have the most up-to-date version of master on our machine.

  • Navigate into the local master branch with $ git checkout master
  • Run $ git pull origin master to pull code from GitHub's master branch into the local master branch.

This command generally triggers one of the following three results:

Example A: No New Changes to Add

If there is no new code on the GitHub master that isn't already in our local master, we will see a message like this. This means local master is up-to-date with remote GitHub master:

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git pull origin master
From https://github.com/test-user/my_project
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Example B: Adding New Changes without Conflict**

If there is new code on the GitHub master branch not already in our local master branch, but Git was able to merge it into local master automatically, we see this message. It confirms new master code was successfully integrated, and our local master now matches the GitHub origin master:

$ git checkout master
Switched to branch 'master'
$ git pull origin master
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/test-user/my_project
 * branch            master     -> FETCH_HEAD
   2833d6c..51f2f03  master     -> origin/master
Updating 2833d6c..51f2d03
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

Example C: Adding New Changes with Merge Conflicts

If there was new content from the GitHub's master branch that isn't already in our local master branch, but Git couldn't merge the new content into local master automatically, we see something like this. This message means our local master is not yet up-to-date with GitHub's origin master, because we must manually fix conflicts:

$ git checkout master
Switched to branch 'master'
$ git pull origin master
From https://github.com/test-user/my_project
* branch            master     -> FETCH_HEAD
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

5. Resolve Merge Conflicts (if necessary)

If conflicts occur we must fix them before continuing. The conflict message from Git (seen above) names all files with conflicts. (For example, the message reads CONFLICT (content): Merge conflict in index.html, so we know index.html contains a conflict.)

Each file listed contains conflict tags highlighting the specific areas where local master and remote GitHub master don't exactly match. These tags look like this:

...
<<<<<<< HEAD
   This is code from the local master branch!
=======
   This is code from the origin master branch!
>>>>>>>
....

Content above the ======= refers to code from the branch we're bringing new code into. Content below is from the branch we are getting new code from.

We resolve conflicts with the following steps:

  • Replace everything between the <<<<<<< and >>>>>>> portions of the conflict tags with the code that should be in the finalized master branch.
  • Remove conflict tags.
  • Thoroughly test everything still works as expected.
  • Commit all changes.

6. Merge Local Master into Local Feature

AKA Check New Code Works with Master Code

Now that our local master matches the origin master on GitHub exactly, we test that new feature code still works when integrated alongside the finalized code from master. It's important we do this on the local feature branch (not the local master), because master is our final draft. We never risk introducing bugs into master.

Essentially: Master is sacred. No feature code ever enters master until we've proven master and feature code work together without issue on the feature branch. Otherwise, we risk damaging the final copy of our project. All experimentation happens on feature branches. Only tried and tested code goes into master.

  • Navigate from the local master branch into the local feature branch by running $ git checkout <local-feature-branch>.
  • Merge local master into local feature with $ git merge master.
  • If merge conflicts occur follow instructions in step 5 above.

7. Add Local Feature Code to Origin Master

AKA Add New Code to Master

Next we ensure the project still works correctly. This confirms new feature code works with finalized master code. When we're certain there's no issue, we add this code to master. There are two primary ways to do this:

  • If all of the collaborators for a project are not physically present to review code, then it is best practice to submit a Pull Request via GitHub so each member can review changes before new code is added to master.

  • If all collaborators are present and approve of the changes to the code, or if we are working solo, it is acceptable to merge into master on our local machine then push the updated master to Github.

First Option: Pull Requests

AKA Merging into Master Using GitHub's GUI

If all collaborators are not present, we submit a Pull Request with the following steps:

a. Push Branch to GitHub

  • Push the feature branch--now containing both feature code and newly-merged code from master--to GitHub by running $ git push origin <feature-branch-name>.

b. Pull Request

We then create a new Pull Request on GitHub's website to request code from the feature branch is merged into master:

  • Navigate to the feature branch on Github and select New Pull Request.
  • In the resulting form, include a description of features this new code will add to the project and other relevant details for teammates.
  • Click Create Pull Request to create a record of the pull request and send it to project collaborators.

c. Review and Merge

Teammates may then view this notification for more information, and options to merge the request into master. More information is available here.

Second Option: Merge to Master

AKA Merging into Master Using the Command Line, then pushing to GitHub

Conversely, if all collaborators are present and have okay'd changes, or if we are working solo, we can merge to master in the local command line with the following steps:

a. Merge Feature into Master

  • Confirm master code has been merged into the local feature branch successfully, everything works exactly as anticipated, and all work is committed.
  • Navigate to the local master branch by running $ git checkout master.
  • Merge code from the feature branch into the master branch by running $ git merge <feature-branch>

Important: If you followed instructions correctly, this should never result in merge conflicts, because you already confirmed all master code works seamlessly with feature code in step 6.

8. Delete

After successfully merging feature code into master, the feature branch may be deleted if no longer in use. The easiest way to do this is through the GitHub repo.

  • Visit the repository and select the Branches option.

branches-option-in-github-repo

  • In the Branches area, select the red delete icon next to the branch we want to delete:

delete-option-in-github-repo

Visual Reference

A visual representation of this workflow:

Git in Teams

Group Project Workflow


Do rely upon this cheatsheet until you've read the full text of this lesson at least once, which provides important considerations and context for this process.

1. Setup Github Repo

  • Create GitHub repo..
  • Add all members as collaborators as explained in the Git With Collaborators: Setup.
  • Clone to each pair's machine with $ git clone <repo-url>.

2. Create Branches

  • Each pair creates (and switches to) a local feature branch with $ git checkout -b <branch-name>.

3. Code

Pairs complete work on dedicated branches.

4. Pull Origin Master into Local Master

When ready to add feature branch code to master, first ensure feature code works with master code.

  • Navigate to local master with $ git checkout master
  • Pull code from GitHub master into local master with $ git pull origin master.

5. Resolve Conflicts (if necessary)

If you receive a Git message reading Automatic merge failed; fix conflicts and then commit the result. you must manually fix conflicts:

  • Locate conflict tags in relevant files. (Message will list affected files.) Content above the ======= is code from branch we're merging into. Below ======= is branch we are getting new code from.
  • Replace everything between the <<<<<<< and >>>>>>> with code wanted in finalized master.
  • Remove the conflict tags, thoroughly test everything works, commit.
  • Repeat for all files containing conflicts.

6. Merge Local Master into Local Feature

Always double-check master code works with feature code on the feature branch (not master).

  • Navigate into local feature with $ git checkout <local-feature-branch>.
  • Merge local master into local feature with $ git merge master.
  • If conflicts occur follow instructions above.

7. Add Local Feature Code to Origin Master

Submit new code to master branch via pull request on GitHub, or merging into master directly:

Pull Requests

  • Push feature branch to GitHub with $ git push origin <branch-name>.
  • Navigate to the feature branch on Github, select New Pull Request. Complete and submit form.
  • Collaborators are notified of PR. May review and merge as detailed here.

Merge to Master

  • Confirm master has been merged into local feature and everything works.
  • Navigate to local master with $ git checkout master.
  • Merge code from feature into master with $ git merge <feature-branch>

8. Delete

After successful merge feature branch may be deleted if no longer in use.

Other Git Commands


For reference, here are other commonly-used Git commands you may require throughout project development:

Configurations

  • $ git config --global user.name "[name]": Sets the user name for all commits.
  • $ git config --global user.email "[email address]": Sets the email for all commits.
  • $ git config --global color.ui auto: Adds useful color to the command line output.

Repositories

  • $ git init: Creates a local repository in the current directory.
  • $ git clone [url]: Downloads a remote repository from the URL and all of its version history in the current directory.

Changing Version History

  • $ git add .: Adds ALL files with changes to the staging area to be committed.
  • $ git add [file]: Adds the named file to the staging area for committing.
  • $ git reset [file]: Unstages the file, but all changes are kept.
  • $ git commit -m "[message]": Records all of the staged files permanently to the version history; message should describe the changes finishing the phrase "This commit will…". Example: $ git commit -m "add AJAX functionality to the comments form"

Reviewing Version History

  • $ git log: Lists commit history for the current branch.
  • $ git status: Lists the files where changes have been made to be committed.
  • $ git diff: Shows differences in files that are not yet staged.
  • $ git diff --staged: Shows differences between the staged file(s) and the last version(s) of the file.
  • $ git diff [branch-1]...[branch-2]: Shows content differences between branch-1 and branch-2.

Branches

  • $ git branch: Lists current branches with an asterisk by the current branch.
  • $ git checkout [branch-name]: Switches to the branch, branch-name.
  • $ git checkout -b [branch-name]: Creates and checks out a new branch named branch-name.
  • $ git branch -D [branch-name]: Delete the branch named branch-name.
  • $ git merge [branch-name]: Merges branch-name version history into the current branch.

Remotes

  • $ git remote: lists currently associated remote repositories.
  • $ git remote add [remote-name-alias] [url]: Adds a new remote repository with the name remote-name using the URL of the remote repo on github.
  • $ git push [remote-name-alias] [branch-name]: Pushes the branch (branch-name) to a remote repository (remote-name-alias).
  • $ git pull [remote-name-alias] [branch-name]: Pulls the latest changes from a remote repository to a local branch repository (e.g. git pull origin master).