This is an old revision of the document!
Overview
Typical workflow for contributing to a public GitHub project, demonstrating the use of branches and remotes. For this demonstration, I'll use a GitHub project I've been contributing to recently – https://github.com/containers/libpod – which is the source of the Docker lookalike podman command (among other things).
Getting a GitHub Account
Unsurprisingly, if you don't already have a GitHub account, get one – examples that follow will refer to my GitHub account rpjday.
Standard GitHub workflow
Fork the project of interest
As a first step, over at GitHub, you need to “fork” the public project of interest – in this case, the public project containers/libpod will be forked to a copy that I will own (also residing at GitHub), rpjday/libpod, and here's the secret of the GitHub workflow.
Once you create your personal fork of that public project containers/libpod, you will not update that personal copy from the public version, nor will you pull from your personal fork; rather, your personal fork will be used as the destination to which you push branches with changes from your local machine that you will ask the containers/libpod maintainers to pull from via “pull requests”.
So go ahead and create that personal GitHub fork before going any further.
Clone your fork to your local machine
Once you've made that personal GitHub fork (in my case, rpjday/libpod), you need to make one more copy of the repository – this one will be clone of your personal fork to your local machine, which represents the working tree in which you create new branches and make local changes that you'll push to your GitHub fork for eventual incorporation into the public project, but here's the trick for clarity.
Since you'll be working with two remotes for this workflow, when you clone your personal fork, use a name other than the default of origin – I'll use the remote name of rpjday to clearly distinguish my personal GitHub fork from the public project containers/libpod:
$ mkdir podman/libpod $ cd podman/libpod $ git clone https://github.com/rpjday/libpod git
Everything here is up to date with your GitHub fork:
$ git status On branch master Your branch is up-to-date with 'rpjday/master'. nothing to commit, working tree clean $
In addition, you can verify that your local clone has one registered remote – your personal GitHub fork:
$ git remote -v rpjday https://github.com/rpjday/libpod.git (fetch) rpjday https://github.com/rpjday/libpod.git (push) $
Again, keep in mind that this remote is where you will push your intended contributions to the public project.
Adding a remote for the main project
You now have to add a remote for the main project itself, since that's where you'll be pulling any new commits from anyone contributing to the project (yourself or anyone else):
$ git remote add progit https://github.com/progit/progit2 $
Verify the new remote:
$ git remote -v origin https://github.com/rpjday/progit2 (fetch) origin https://github.com/rpjday/progit2 (push) progit https://github.com/progit/progit2 (fetch) progit https://github.com/progit/progit2 (push) $
You can see this information in your .git/config file:
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] url = https://github.com/rpjday/progit2 fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [remote "progit"] url = https://github.com/progit/progit2 fetch = +refs/heads/*:refs/remotes/progit2/* $
Keeping up to date
Before you even start contributing to the main project, there are three steps involved in keeping up with everyone else's contributions.
First, fetch from the upstream progit remote into the remote tracking branch progit/master:
$ git fetch progit
Next, manually merge any new content into your local master branch:
$ git merge progit/master
Finally, push this new content to your GitHub fork of the project:
$ git push origin master
Do all of this on a regular basis to keep everything in sync.
Contributing changes
Contributing changes to the main project involves three steps:
- Make and commit some local changes (preferably on a feature branch).
- Push those changes (that branch) to your GitHub fork.
- Make a “pull request” to have the main project accept your commit(s) on that branch.
First, create a new branch, make and commit a silly change:
$ git checkout -b topic/rpjday/issue42 Switched to a new branch 'topic/rpjday/issue42' $
Make a simple change to README.asc and commit it:
$ git checkout -b topic/rpjday/issue42 Switched to a new branch 'topic/rpjday/issue42' $
$ git commit -a -m "fix issue42" [topic/rpjday/issue42 77fad5f] topic/rpjday/issue42 1 file changed, 1 insertion(+), 1 deletion(-) $
$ git show
commit 77fad5f0aadd229628baa7811b0b49c7580d96f0 (HEAD -> topic/rpjday/issue42)
Author: Robert P. J. Day <rpjday@crashcourse.ca>
Date: Wed Feb 14 07:06:42 2018 -0500
fix issue42
diff --git a/README.asc b/README.asc
index d7810fd..126bfd4 100644
--- a/README.asc
+++ b/README.asc
@@ -1,4 +1,4 @@
-= Pro Git, Second Edition
+= Pro Git, Second Edition (rday change)
Welcome to the second edition of the Pro Git book.
$
At this point, you can push this new branch to your GitHub fork:
$ git push origin topic/rpjday/issue42
And over At GitHub
Provided you're logged into your account at GitHub, you'll suddenly see the appearance of a new branch sillyb. If you think it's ready to go, you can select “Compare & pull request” to examine and confirm that you want to hand that off to the main project.
If all goes well and your change is accepted and committed, you will have to perform the two earlier steps to fetch and merge your changes into your local clone into the master branch:
$ git fetch progit $ git merge progit/master
In addition, you can now delete the sillyb branch if you have no further use for it.