The majority of projects in our lab are hosted on github.com. GitHub is a web application that can be used for collaboration, code review, and code management. It is popularly used in open source projects and by distributed developers. Contributions to our projects are expected to be made using pull requests to repositories of their GitHub organization. For example, the Seattle repositories are hosted on the SeattleTestbed organization.
Git is a free and open source distributed VCS (Version Control System). A VCS helps manage changes made to files. Users can run Git on their local computers and upload changes to remote repositories and files hosted on GitHub. Contributors can edit files locally, upload their changes to GitHub, and then initiate a pull request. The following document covers the basics of using Git and submitting a pull request to one of our project's GitHub repository.
git-scm.com provides platform-specific installers for Mac, Linux, and Windows users.
After installing Git, the next step is for the user to configure his/her identity (username and email address) so that Git can fully log the author of a commit. All Git commits include the user's username and email address.
To configure your Git identity, open the Terminal and type git config --global user.name "user's name"
, which will allow you to configure Git on
your local machine. The user.name is arbitrary, but it is customary to use
your full name.
Each repository you create will use the same user (author) configuration if you use the global flag (as in the provided example).
$ git config --global user.name "John Smith"
$ git config --global user.email "[email protected]"
You can check your configuration settings by typing the following command:
$ git config --list
If GPG is installed on your system, you can configure Git to sign your commits.
$ git config --global user.signingkey <your GPG key ID>
GitHub provides more thorough instructions on how to tell Git about your GPG key.
There is also a convenient Git command to automatically sign all of of your commits:
$ git config commit.gpgsign true
Note: The command above requires Git version >= 2.0.0.
Before a pull request can be submitted to a Secure Systems Lab repository, a user account (free) must be created on GitHub. This user account is also needed to create new repositories and fork ones that already exist on GitHub.
A GitHub user account can be created at https://github.com/join
Once users create their accounts, user-specific home pages are created. For
example: https://github.com/<username>
. A user-specific home page can contain
repositories that the user has created or forked, contribution activity, and
organizations he/she has joined.
Forking refers to making a copy of a GitHub repository and saving it to your GitHub user homepage. GitHub provides general instructions on creating and managing forks and pull requests.
Forking a repository, SeattleTestbed in
this example, requires clicking the fork
button on the selected
repository's GitHub page, which creates a copy of the repository and saves it
to a repository directly controlled by the user (on the user's GitHub home
page). The URL of the forked repository can then be used with Git to create
and save a local copy.
Navigate to the repy_v2 repository
and click on the fork
button in the upper right-hand corner of the page.
The git clone
command creates a local copy of a remotely hosted GitHub
repository. So far, the repy_v2
repository has only been copied and saved
to the user's GitHub home page. In the following example, the repy_v2
SeattleTestbed
repository is cloned to create a local Git repository.
$ git clone https://github.com/<username>/repy_v2
Cloning into 'repy_v2'...
remote: Counting objects: 1547, done.
remote: Total 1547 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1547/1547), 1.06 MiB | 0 bytes/s, done.
Resolving deltas: 100% (778/778), done.
Checking connectivity... done.
A repy_v2
folder is created in the local, current working directory.
Before issuing Git commands pertaining to this repository, you need to
change directories to either the cloned repository's directory, or to one
of its sub-directories. For example:
$ cd repy_v2/
Setting an alias for a repository can help developers better manage repository
changes and keep local and remote repositories in sync. The alias is a string
that refers to the repository by name instead of the repository's full URL. In
the example below, the original
repy_v2 repository is given the
upstream
alias:
$ git remote add upstream https://github.com/SeattleTestbed/repy_v2.git
Fetching and merging the latest changes of upstream
(remembering that the
upstream
alias points to the original repository) can be done with Git's
pull
command. The pull
command fetches changes made to the remote
repository and merges them into your local repository.
Branches are multiple working versions of a master project (or document). The
main branch is the master repository and multiple, local branches of this
master may be created by users so that they can work on the project before
committing their work to the master document. The pull command expects to see
a (by default, the master) branch name, which the user will find on the
project's main repository.
Information on creating a new branch is in the next section, Add a New Branch Locally
.
The GitHub help has more information on keeping your forks in sync with upstream.
$ git pull upstream master
From https://github.com/SeattleTestbed/repy_v2
* branch master -> FETCH_HEAD
* [new branch] master -> upstream/master
Already up-to-date.
First, list all known local branches of the repository, by typing the following:
$ git branch
* master
Next, to add a new branch, which is the preferred method for working on and
adding new features, type git branch new_branch
, where new_branch
is the name of the new branch:
$ git branch new_branch
The next step is to switch to the newly created branch:
$ git checkout new_branch
Switched to branch 'new_branch'
Note: git checkout -b [branchname]
is a shortcut to create and checkout a
new branch.
Create a LICENSE
file and save it to the local machine. You do this by
opening a new document in a text editor and saving as LICENSE
in the current
directory. In the LICENSE
file you can include an open-source license for the
project. The MIT license
is typically used for most of our lab's projects.
The next step is to ask Git if it can find the LICENSE
file, by asking it to
identify all untracked files (on the local repository):
$ git status
On branch new_branch
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE
nothing added to commit but untracked files present (use "git add" to track)
Git indicates that the LICENSE
file is untracked, so the first command (git
add) will add it. The second command (git status) will tell us whether the file
has been added successfully.
$ git add LICENSE
$ git status
On branch new_feature
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: LICENSE
After adding the file it must be committed. By committing a file, Git creates a
message about the file that will be transmitted once the file is ready to be
pushed to the master branch. A Git message should be descriptive and mention
the reason for the change, or changes, to be committed. In the following
example, the -m
flag (for message) is used and a commit message is appended
in quotes.
$ git commit -m "Add a LICENSE file to the project"
[new_branch 7660f34] Add a LICENSE file to the project
1 file changed, 1 insertion(+)
create mode 100644 LICENSE
If you want to check to see that all files have been added and committed, type
git status
again. The status should show that the directory is clean, as in
the example below:
$ git status
On branch new_branch
nothing to commit, working directory clean
To get a list of commit messages made thus far, type git log
. This will show
the user's information and the commit message (in this case Add a LICENSE to the project
):
$ git log
commit 3c9b1d0068075fdac6ed928f8e5a27ac3253ca5e
Author: <username> <[email protected]>
Date: Tue Sep 2 14:46:36 2014 -0400
Add a LICENSE to the project.
This step will push the branch to the remote repository controlled by the user (the forked version that you created earlier). The changes committed in the "Commit a New File to the Branch" so far exist on the local repository. The earlier commit message, along with the file, are pushed to the user's remote repository.
$ git push origin new_branch
Username for 'https://github.com': <username>
Password for 'https://<username>@github.com':
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 308 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://github.com/<username>/repy_v2
* [new branch] new_branch -> new_branch
After the files are pushed, you (the user) can initiate a pull request to suggest your changes for inclusion in the original upstream repository.
Continuing with the example of SeattleTestbed/repy_v2
,
visit the forked repy_v2
repository and click on the "New pull request" button next to
the drop-down list of branches. The next page is where you will preview the
commits and write/post a summary or comments about the changes you made. The
image below shows where to locate the pull request button.
A page (containing the user's Pull Request) is generated by GitHub and viewable
by both the user and developers of the repy_v2
repository. A
repy_v2 developer can review the
user's changes and either accept, decline, or ask that the user addresses
issues with the pull request. The pull request's page provides a section to
enter comments and allow the user and
repy_v2 developers to collaborate.
The user can make additional changes to the pull request (for example, to
address an issue raised) by pushing commits to the user's forked repository.
In the following example, the user edits the LICENSE
file and saves the
changes before issuing git add LICENSE
:
$ git add LICENSE
$ git commit -m "Add missing section to LICENSE noticed by reviewer"
$ git push origin master
Merge conflicts might occur with Git's push or pull actions if multiple contributors attempt to modify the same section of a file, and merge their conflicting modifications to the server’s “master" branch. For example, suppose one contributor wants "foo" to appear in the first three characters of a file, while another contributor desires "bar". When a merge conflict occurs, the affected contributors must mutually resolve the conflicting section. That is, the file in the previous example must be edited to produce one unique version of the file; either "foo" appears in the first three characters, or "bar" does.
If Git detects a merge conflict after a pull or merge action, it inserts special markers in the conflicting section(s) of the file to indicate what needs to be resolved:
<<<<<< HEAD
foo
======
bar
>>>>>>
The text between <<<<<< HEAD
and =====
is what is currently on the server’s
“master” branch. The text between =====
and >>>>>>
is what is being merged and
causing the conflict. To resolve the merge conflict, a contributor must open
the file in a text editor and manually remove the merge conflict markers and
either keep what is currently on the “master” branch or what is being merged.
In the merge conflict example above, a contributor would keep either the text
“foo” or “bar”, and remove the rest of the markers inserted by Git. To
finalize the merge conflict, the contributor must commit the resolved changes.
Steps to resolve the merge conflict:
Edit the file containing the merge conflict in a text editor. To discard what is currently on the server and replace it with “bar”, delete “foo” and the three inserted markers.
-
Save the file.
-
$ git add
-
$ git commit
-
$ git push
The following page provides a comprehensive guide on resolving merge conflicts: https://help.github.com/articles/resolving-a-merge-conflict-from-the-command-line/
Typing git help -a
on the command-line outputs the full list of commands
supported by Git. Consult Git's help pages for more information about each
command.
Zackperdue.com
is another resource that covers useful Git commands, and GitHub's Git Cheat
Sheet
is a handy reference.
The section below lists some useful, common Git commands.
To show changes/differences in the LICENSE
that have not been committed:
$ git diff LICENSE
diff --git a/LICENSE b/LICENSE
index 70a3d0f..93bce69 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1 +1,2 @@
LICENSE file.
+new line added here.
To mark LICENSE
as removed and stage it for removal:
$ git rm LICENSE
To unstage the modified LICENSE
file and reset its contents to the current
version on the repository:
$ git reset HEAD LICENSE
To rename a file or to move it to a new location and let Git know of the change:
$ git mv source_file destination_file
To temporarily store modified files in order to change branches:
$ git add temporarily_modified_files
$ git stash save "Temporary commit message for modified files"
To display stashed contents and apply them on the current branch:
$ git stash list
$ git stash pop