To help illustrate collaborating on a project using Git/GitHub, consider the following two roles you can fulfill: programmer and manager.
Programmers will contribute code and issue pull requests, while managers integrate the code by merging the pull requests into the repo.
Manager:
- Create a repo locally, using
$ git init
. - Create a remote version of this repo on GitHub (using
hub create
if you wish). - Ensure you have a remote named origin:
$ git remote -v
Programmer:
- Identify the repo created by your manager on GitHub.
- Fork the repo to your own account.
- Use
$ git clone <link to your repo>
to copy your forked repo locally. Obtain the link to your repo by clicking the green "Clone or download" button. cd
into the newly created project folder.- Now add a link to the manager's repo as well:
$ git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
- Ensure that you have two remote links named
origin
&upstream
:$ git remote -v
- Ensure you are notified of changes to the project by clicking the Watch button near the top right of the manager's repo. Then make sure you GitHub account's notification settings are adjusted to notify you via email, etc.
Manager & Programmer:
- Frequently ensure that you have the most recently merged code on your local computer:
- Checkout the
main
branch withgit checkout main
. Only pull when you are onmain
. - Now you can
$ git pull upstream main
. Managers will always useorigin
in place ofupstream
.
- Checkout the
- Use a feature branch with
$ git checkout <feature_branch_name>
; add-b
to create a new branch if necessary. Name the branch after the feature you are working on implementing in that branch. You should never write code while in themain
branch. - Write some code!
- When you have completed a feature:
- Commit your code as usual...
$ git push origin <feature_branch_name>
- On your GitHub repo's page, find and click the Pull Request button.
- FYI, multiple commits are grouped within a single open pull request.
- Go back to step #2.
Manager:
- If GitHub states that the pull request can be merged automatically - do it!
- If GitHub states there will be conflicts, and the merge is smallish, it is still possible to merge online by following the instructions.
- If the request is very comprehensive and may cause plenty of merge conflicts, the manager may decide to test and merge the pull request locally/manually by clicking command line instructions and following the steps listed.
- After a merge, ensure your team members pull the recent changes into their local repo ASAP.
- Try to divide up work so that programmers don't make changes to the same file between merges.
- When notified that branches have been merged into
main
by the manager, immediately bring your local repo up to date so that you are working with the latest and greatest:- We're going to need to checkout the main branch to update it, however, sometimes Git will not allow us checkout a different branch if there are uncommitted changes in the current branch. The solution is to either
stash
orcommit
the changes first. Please read this StackOverflow for how to resolve this scenario if Git does not allow the next step ($ git checkout main
). $ git checkout main
$ git pull upstream main
Manager usesorigin
instead ofupstream
$ git checkout <feature_branch_name>
$ git merge main
This brings the latest code into your feature branch so that you are always developing with the latest and greatest.
- We're going to need to checkout the main branch to update it, however, sometimes Git will not allow us checkout a different branch if there are uncommitted changes in the current branch. The solution is to either
- Making frequent and small commits and pull requests will help minimize merge conflicts.
Note: When merging the latest and greatest into your feature branch, it's possible to create merge conflicts too. So managers aren't the only ones who get to enjoy fixing merge conflicts!
- You will/should be in your feature branch when the conflicts occurred.
- Typing
$ git status
will show you which file(s) have conflicts. - You will need to edit those files to remove the markers and fix up the code to what it "should" be - if in doubt what, consult your manager or other teammates.
- After fixing the commits:
$ git add -A
$ git commit -m "Fix merge conflicts"
- Continue developing as usual.
To visualize the history of commits made to the repo we use the git log
command. There are several options, but this format works well:
$ git log --decorate --graph --oneline
$ git init
Initializes a new local repository and begins version tracking. Creates a hidden directory that tracks info about the repository, including remote repositories.$ git clone <ssh_or_http_url>
Clones a remote repository as a new local repository with the given connection format (SSH or HTTPS).$ git remote add <remote_name> <ssh_or_http_url>
Connects your repo to a new remote at the given URL, via the given connection format (SSH or HTTPS), and names it with the given name.
$ git branch <branch_name>
Creates a new branch with the given name.$ git checkout <branch_name>
Moves you to the branch (or commit in history) with the given name.$ git checkout - b <branch_name>
Creates a new branch and checks it out, all in one!$ git merge <branch_name>
Merges the branch cwith the given name into the current branch.
$ git add <file_name>
Adds changes made to the given file to the staging area.$ git add .
Adds all changes (creating, updating and removing files), to files in this directory and sub-directories, to the staging area.$ git add -A
Adds all changes (creating, updating and removing files), in all files, to the staging area.$ git add -p
Adds updates in all staged files to the staging area, but runs you through all the changes step by step.
$ git commit -m "awesome commit message"
Saves a snapshot of the filesystem including any changes that have been added/staged as a commit. It saves the commit with a simple description, or message, given after-m
.$ git commit
Commits as above, but takes you to a text editor (nano
) to edit the commit's message.
$ git status
Prints out the current "tracking state" of the repo. The state includes information about changes, additions and deletions of files, whether or not these changes have been added/stages, and sometimes even any merge conflicts.$ git log
Prints out the commit history of the current branch of the current repo.$ git branch
&$ git branch -v
Prints out a list of all available branches in the repo.$ git remote
&$ git remote -v
Prints out a list of all available bremotes connected to the repo.$ git diff <branch_or_commit_name>
Prints out information about differences, as insertions (in green) and deletions (in red), between the current commit and the given commit (or the most current commit in the given branch).
$ git push (-u) (<remote_name> <branch_name>)
Push, or send, commits to remote at the given branch.-u
saves the remote and branch names as default for future use.$ git fetch <remote_name> <branch_name>
Fetch, or receive, commits from a given remote at the given branch. Stores these commits in either the named commit, or in a special, new branch.$ git pull <remote_name> <branch_name>
Performs agit fetch
into a new branch, then merges it into the current branch and removes the fetched branch.
Articles and tutorials on branching and workflows in Git:
- Git Branching
- Common Git Workflows
- In-depth Discussion of a Workflow
- 'Reset Demystified' (helps to understand the structures of Git)
- A Git Branching visualization game!