|
|
(4 intermediate revisions by 3 users not shown) |
Line 1: |
Line 1: |
| = Scripted git commands for a linear history =
| |
|
| |
|
| * All developments should use the following scripts and workflow to maintain a linear git history in TubeTK
| |
| * These scripts are published online at
| |
| ** http://www.dinnermint.org/tutorial/dead-simple-git-workflow-for-agile-teams
| |
|
| |
| == Using the Scripts ==
| |
|
| |
| The scripts below should be used in a workflow as:
| |
|
| |
| > git branch *newTopic*
| |
| > git checkout *newTopic*
| |
| > *do some work*
| |
| > git add *files*
| |
| > git commit *files*
| |
| > gitupdate
| |
| > *do some more work*
| |
| > git add *files*
| |
| > git commit *files*
| |
| > gitupdate
| |
| > gitship
| |
|
| |
| == gitupdate (script) ==
| |
|
| |
| #!/bin/sh -x
| |
| # hack: Merge the latest changes from the master branch into your current branch
| |
| ref=$(git symbolic-ref HEAD 2> /dev/null) || exit 0
| |
| CURRENT="${ref#refs/heads/}"
| |
| git checkout master
| |
| git pull origin master
| |
| git checkout ${CURRENT}
| |
| git rebase master
| |
|
| |
| == gitship (script) ==
| |
|
| |
| #!/bin/sh -x
| |
| # Git workflow ship script from: http://reinh.com/blog/2008/08/27/hack-and-and-ship.html
| |
| # git name-rev is fail
| |
| ref=$(git symbolic-ref HEAD 2> /dev/null) || exit 0
| |
| CURRENT="${ref#refs/heads/}"
| |
| git checkout master
| |
| git merge ${CURRENT}
| |
| git push origin master
| |
| git checkout ${CURRENT}
| |
|
| |
| === Hidden details ===
| |
| * The above scripts and workflow implement the following, and save you much typing and potential errors!
| |
| * Most importantly, do your work in branches, not in master!
| |
| # Keep a local master branch which only is a pointer to the gitorious master (does not contain local changes)
| |
| # Make development modification in a local branch (the "topic" branch)
| |
| # To push changes made on your topic branch to TubeTK:
| |
| ## gitupdate
| |
| ### Does a git pull on master: this ensures that your local master branch is up to date, by fetching and merging all changes that have occurred on the gitorious TubeTK master
| |
| #### '''git checkout master'''
| |
| #### '''git pull origin master'''
| |
| ### Does a git rebase of the topic branch onto master: this replays the commits from your local master branch onto your local topic branch, maintaining a linear history
| |
| #### '''git checkout topic'''
| |
| #### '''git rebase master'''
| |
| ## Fix any conflicts that result
| |
| ### Edit files
| |
| ### '''git add -u'''
| |
| ### '''git rebase --continue'''
| |
| ## gitship
| |
| ### Merges the topic branch onto the master branch: this will add the commits of your local topic branch to your local master branch, and will result in an fast-forward merge.
| |
| #### '''git checkout master'''
| |
| #### '''git merge topic'''
| |
| ### Pushes your local master branch: this will add your contribution to TubeTK (pushes your changes to the gitorious TubeTK master)
| |
| #### '''git push origin master'''
| |
| ### Continuing development is done in your local branch
| |
| #### '''git checkout topic'''
| |
|
| |
| = Use multiple commits to organize changes =
| |
|
| |
| When appropriate, organize your changes into a series of commits where each commit is a logical step towards your ultimate goal. For example, first factor out some complex code into a new function. Then, in a second commit, fix an underlying bug. Then, in the third commit, add a new feature which is made easier by the refactoring and which would not have worked without fixing that bug.
| |
| This is helpful to reviewers, because it is easier to see that the "factor out code into new function" step was right when there aren't other edits mixed in; it's easier to see that the bug is fixed when the change that fixes it is separate from the new feature; and so on.
| |
|
| |
| = Get changes from others =
| |
|
| |
| == From the central repository ==
| |
|
| |
| To get changes that have been committed to the location you originally cloned from:
| |
| git stash # To push your uncommitted local changes to a stack
| |
| git pull --rebase
| |
| git stash pop # To apply the changes on the stack to the update local repository
| |
|
| |
| == From other repositories ==
| |
|
| |
| Pull changes made by another developer in his public repository but not yet committed to the central repository:
| |
| git pull git://some-other-repo.git master
| |
|
| |
| 'git remote' can be used to manage short names for repositories that you frequently pull from.
| |
|
| |
| == From patches ==
| |
|
| |
| Apply a patch from another developer, preserving the other developer's identity as the patch author:
| |
| git am --signoff patch.mbox
| |
|
| |
| == Work with branches ==
| |
|
| |
| To list just the branches in your local repository:
| |
| git branch
| |
| To list all the branches in the remote repository:
| |
|
| |
| git branch -r
| |
| To check out a branch for example the 2.4 branch:
| |
|
| |
| git checkout -b vBeta origin/vBeta
| |
| To work on the Beta branch instead of 'master' ('master' is the git equivalent of cvs 'TRUNK'):
| |
|
| |
| git branch --track vBeta origin/vBeta
| |
| git checkout vBeta
| |
| After you branch, you can switch freely between master and branch:
| |
| git checkout master
| |
| git checkout vBeta
| |
| You can create your own branch based off another branch:
| |
|
| |
| git branch my-topic master
| |
| git often uses "topic" as a placeholder for a branch name, because everything in a branch should be on one "topic"--a topic might be to add feature X, refactor subsystem Y, only fix bugs from version Z, and so on.
| |
|
| |
| == If you prefer to use different directories for different branches ==
| |
|
| |
| The following sequence creates "tubetk-vBeta" alongside "tubetk", then uses 'git relink' to save disk space, then switches to the vBeta in the tubetk directory:
| |
| cp -r tubetk/ tubetk-vBeta
| |
| git relink tubetk-vBeta/ tubetk/
| |
| cd tubetk-vBeta
| |
| git branch vBeta origin/vBeta
| |
| git checkout vBeta
| |
|
| |
| = Share your changes with others =
| |
|
| |
| == Choose an appropriate starting point ==
| |
|
| |
| For new features, use the git 'origin/master' branch as the starting point.
| |
| For bugfixes, use the merge-base of master and vBeta. You can make a bugfix and merge it into both branches like so:
| |
|
| |
| git checkout $(git merge-base origin/vBeta origin/master)
| |
| git checkout -b descriptive-bugfix-branch-name
| |
| edit/compile/test/commit
| |
| git checkout master
| |
| git merge descriptive-bugfix-branch-name
| |
| compile/test
| |
| git checkout vBeta
| |
| git merge descriptive-bugfix-branch-name
| |
| compile/test
| |
|
| |
| Check with tubetk developers before pushing changes to vBeta. If your bugfix is approved for vBeta, then it will also be fixed on master when changes in the branch are merged up.
| |
|
| |
|
| |
| == Prepare commits to share with fellow developers ==
| |
|
| |
| With git, it's possible to record every edit and false start as a separate commit. This is very convenient as a way to create checkpoints during development, but often you don't want to share these false starts with others.
| |
|
| |
| Git provides two main ways to do this, both of which can be done freely before you share the change:
| |
| * 'git commit --amend' lets you make additional changes a part of the last thing you committed, optionally modifying the commit message as well. Use this if you realized right away that you left something out of the commit, or if you typo'd the commit.
| |
| * 'git rebase --interactive origin' lets you go back through each change made since 'origin', possibly editing it or combining ('squashing') it with another change. In the most extreme case, you can 'squash' it into a single commit, if there's no value to other developers in seeing the individual steps.
| |
|
| |
| == Send patches through e-mail or the web ==
| |
|
| |
| When you think your changes are ready to be used by others, you can share it in the form of a patch. Make a series of patches for each commit in your local branch but not in 'origin':
| |
| git format-patch -M origin
| |
| This creates a number of files with names like
| |
| 0001-my-well-intentioned-change.patch
| |
| These patch files are suitable for putting on a webserver or for sending as e-mail with your favorite mail client or git-send-email (some configuration required).
| |
|
| |
| To submit a patch, email it to one of the TubeTK Developers.
| |
|
| |
| == Push changes to the central repository ==
| |
|
| |
| If you've been approved to directly push your changes to the central repository, then after some initial setup of ssh keys it's a fairly simple process:
| |
| git pull --rebase
| |
| # resolve any conflicts, but generally there won't be any
| |
| git push
| |
| If another developer pushed between your pull and your push, you will have to pull and then push again. This isn't expected to happen very frequently, but it will happen more frequently than with cvs since it's required when any file changed, not just when a specific file being committed changed. It is also best to use "git pull --rebase" in this case, this will cause the changes from the central repository to be positioned before your own changes (thus skipping a merge).
| |
|
| |
| == Push changes to your own public repository ==
| |
|
| |
| You can host a public repository to which you "push" and from which others can "pull". If you don't have a server of your own to do this, services like github and gitorious are free for open source projects. After you push to your own public repository, other developers can browse your changes or "pull" them.
| |
|
| |
| = Policy =
| |
|
| |
| Just because a thing can be done with git doesn't mean it should be done.
| |
|
| |
| == Prefer "rebase" ==
| |
|
| |
| Use "git pull --rebase" instead of bare "git pull" in order to keep a nice linear history. When you "--rebase", you always retain your work as revisions that are ahead of origin/master, so you can do things like git format-patch them to share with others without pushing to the central repository.
| |