Open main menu

Difference between revisions of "Git tips"

7,749 bytes added ,  15:30, 30 May 2011
Add Fingolfin's Github Fork Workflow Notes.
(→‎Don'ts: Mention restriction of branches on the main repository)
(Add Fingolfin's Github Fork Workflow Notes.)
 
Line 51: Line 51:


TODO
TODO
=== Github Fork Workflow ===
==== Preliminaries ====
I assume that you are familiar with the basics of git, have a github account, and have adjusted your local git config to contain info about your github user account, as per <http://help.github.com/git-email-settings/>.
In addition, if you are on a unixy system, I recommend taking a look at the "hub" tool <http://github.com/defunkt/hub> which makes it easier to fork repositories, clone other people's repositories etc. But I will not assume that you are using it.
==== What is a github fork and why use it? ====
A github fork is a clone of another github hosted repository (say, scummvm/scummvm) which is located under your github user account (say fingolfin/scummvm). It allows you to publish changes you make to ScummVM (preferably in a topic branch), but which you do not want to / cannot push to the regular scummvm repository yet.
It's a good place to stage bigger changes. It's also very easy to ask the ScummVM team to review your changes made in a public github fork, and to optionally merge them into scummvm/scummv, via a so-called "pull request" <http://help.github.com/pull-requests/>.
==== How to create a github fork? ====
See here <http://help.github.com/fork-a-repo/>. Essentially, you use the "fork" button on <https://github.com/scummvm/scummvm>. Then, clone your new fork. You can now work in this clone as in a clone of scummvm/scummvm, but pulls and pushes now go to / come from your fork.
==== How to use your github fork? ====
In the following, I will try to describe a workflow that is hopefully effective, safe, and relatively easy to use. Other workflows are possible, and you are welcome to use them; the one here tries to minimize the risk of messing up the scummvm/scummvm repository, and to avoid situations in which you need to do complicated stuff you correct mistakes you made.
Over time, your fork will start to *deviate* from scummvm/scummvm. In particular, it will not automatically receive updates made to scummvm/scummvm. So, you will want to regularly sync your fork and its master branch against the master branch of scummvm/scummvm. This is easiest if your fork's master branch never receives any custom commits; always keep it identical to (a possibly old version of) the scummvm/scummvm master branch. All your own work should go to branches, ideally one branch for every topic you are working on (so-called topic branches).
==== Initial Setup ====
This is how I did the initial setup for it for my personal fork:
1) Clone the fingolfin/scummvm repository
  git clone git@github.com:fingolfin/scummvm.git scummvm-fingolfin
  cd scummvm-fingolfin
2) add a "remote" for the official scummvm/scummvm repository (I will use "upstream" as remote name, to match the github docs; personally, I prefer using the remote "username", so in this case I would have used "scummvm" instead of "upstream". Pick whatever you like)
A read-only remote can be added like this:
  git remote add upstream git://github.com/scummvm/scummvm.git
If you have write access, you may want to instead add a read+write remote, e.g. using the SSH protocol:
  git remote add upstream git@github.com:scummvm/scummvm.git
3) Retrieve the latest data from scummvm/scummvm
  git fetch upstream
==== Sync master branches ====
To sync my master branch with the upstream master branch, I can now do this, assuming that "master" is the currently active branch (if not, use "git co master" to switch to it):
    git pull upstream master
    git push
==== Working with code ====
Usually, any code I make goes first into a branch:
  git co -b new-cool-feature
Let's edit a file (e.g. modify base/main.cpp to print "hello, world"). Commit this as usual; note that the commit will land on the new-cool-feature branch, not master.
  ... edit base/main.cpp ...
  git add base/main.cpp
  git ci -m "BASE: Add new cool feature"
You can check the difference between the two branches:
  git diff master..new-cool-feature
Now we want the rest of the world to be able to see our marvelous new code, so let's push it to a new branch on our github fork, with identical name:
  git push origin new-cool-feature
With this we have established a connection between our local "new-cool-feature" branch, and the "new-cool-feature" branch on github. From now on we can just do "git push". So let's edit base/main.cpp again, this time maybe by printing a "goodbye, world" at the end. Then, let's commit and push the changes:
  ... edit base/main.cpp ...
  git add base/main.cpp
  git ci -m "BASE: Even better new feature"
  git push
You can look at the result here: <https://github.com/fingolfin/scummvm/tree/new-cool-feature>
At some point, you may want your work to be integrated into the official ScummVM tree. As mentioned above, the easiest way (if you are not a committer) probably is to submit a pull request <http://help.github.com/pull-requests/>. Even people who do have write access often use this, in order to receive feedback on their code.
If you have write access and just want to integrate your changes, do the following (I'll assume you do a merge here, but you can of course also do a rebase):
  git co master
  git pull upstream  # ensure we are in sync with upstream
  git merge new-cool-feature
  git push upstream  # push to upstream
  git push            # push to your fork
[question to the experts: maybe we want to suggest use of --no-ff for the merge ?]
Note: In reality, I sometimes make an exception and skip the creation of a (topic) branch. E.g. if I only want to commit a quick fix to some code. In that case, I might commit the fix into my local master branch, then push the result to both my fork and scummvm
  git co master
  git pull
  ... edit files, add and commit them ...
  git push upstream
  git push
 
==== Cleaning up your existing clones / checkouts ====
Maybe you were already using a fork, but were following a different model (or no model at all ;) and would like to adapt to this. E.g. maybe you made commits directly to your master branch, then merged changes from scummvm/scummvm's master branch into that, and now have a messy history which intermingles your own work with upstream work.
Cleaning this up is usually quite simple. Let's assume the most simple case, namely that you made no branches at all and did all your work on master. (If you did use branches, you need to adapt this. Feel free to ask here or on our IRC channel if you need help.)
So, let's assume you are in your local clone of your fork, with master as sole active branch. Make sure that the upstream remote has been added, as described above, so
  git remote add upstream git://github.com/scummvm/scummvm.git
or
  git remote add upstream git@github.com:scummvm/scummvm.git
Now, we fetch the upstream changes, and *rebase* our master branch on that:
  git fetch upstream
  git rebase upstream/master
If all went fine, then this just completely. If you are in bad luck, this will cause an error, and you will have to resolve conflicts. It prints instructions for how to do that. Feel free to ask here or on IRC for assistance with resolving the issues. In the worst case, you can just use
  git rebase --abort
to give up.
But let's assume the rebase worked fine, or that you managed to make it work by resolving any conflicts. Now it's time to move any work you have done on master to a branch, so that we don't need to worry about this again in the future. Also, we will reset your local master branch to match the upstream master branch
  git br BRANCH_NAME
  git reset --hard upstream/master
Finally, we can push your work back to your fork:
  git co master
  git push origin master
  git co BRANCH_NAME
  git push origin BRANCH_NAME
TrustedUser
574

edits