Standard Feature-Branch Workflow
This is our default workflow. The advantage of maintaining a clean "master" branch is that it allows easy branching to address separate features or to quickly fix a bug. Use of rebases instead of merges prevents local merge commits.
- Update "master" branch.
> git pull upstream master
- Create a new feature-branch "feature1"
> git branch feature1 master > git checkout feature1
- Do some work on your feature, add and commit it
> git add File1, File2 > git commit -m "Working my feature"
- OPTIONAL: When you're ready to push up, squash all of your commits together first
> git reset --soft master > git commit -m "unified feature commit"
- When you're ready to push your work up to get pulled in, make sure you're up-to-date first
> git checkout master > git pull upstream master
- "master" is now up-to-date. Switch back to your branch and rebase your work on top of the new "master"
> git checkout feature1 > git rebase master
- Push up to github
> git push origin feature1
- Issue pull request
- When processed, update "master" to pull down your official change, delete "feature1"
> git checkout master > git pull upstream > git branch -D feature1
Staying up-to-date
Refreshing your feature branch can be done at any time by calling commands 4-6
Handling merge issues
When you rebase your feature on-top of new stuff in your "master", you may have to handle file merges. Please note that step 4, squashing all of your work into a single commit is encouraged, otherwise you may end-up processing merges on the same file for every commit you're rebasing.
How do you know you're conflicted? Look for the big "CONFLICT" in the results when you issue the rebase
> CONFLICT (content): Merge conflict in index.html
You can either use your IDE to handle the conflicts or if you've setup the git merge-tool (http://gitguru.com/2009/02/22/integrating-git-with-a-visual-merge-tool/), issue the following from the command-line
git mergetool CONFLICTED_FILE
Exiting the mergetool should mark the file as resolved. Depending on your mergetool, you may be prompted to tell Git if the merge was successful.
After all conflicted files have been resolved, tell rebase to continue
git rebase --continue
If you've made a mistake and just want to cancel out of the rebase, issue the following command:
git rebase --abort
Advanced Git Topics
Cherry-Picking
When developing a fix or feature across multiple branches, you often cannot just merge one branch onto another. Think of a fix that needs to be applied to versions 1.0, 2.0 and 2.2. Merging would bring in more than your one fix. In this scenario cherry-picking is the answer. Basically it's capturing a patch-file of one commit and applying it to another branch to create a new commit.
Steps to Cherry-pick
Identify the SHA(s) code for the commit you want to pick-over to another branch. git log or your IDE's history will work fine.
git checkout TARGET_BRANCH git cherry-pick 724d9acd 3d4fcf9e
Just like merging or rebasing, you may have to handle a merge. If so, run git mergetool and then git cherry-pick --continue
Resetting
The reset command does a lot of diferent things. The most basic form is as follows:
git reset FILE1
This will replace the file in your working directory with the lasted one in your HEAD. An optional second parameter is the commit from which to pull the file. And since branches are just named commits, you can use a branch name as well
git reset FILE1 COMMIT_SHA_OR_NAME
The second use of reset actually moves the branch to point to another commit. This is often a commit further back in the branch, but can be any commit from any branch, remote or even an orphaned commit in the reflog. You'll notice we don't specify a file, that's because we're resetting the branch!
git reset --STYLE COMMIT_SHA_OR_NAME
The style of reset you apply makes a huge difference in the result.
--soft
Does not touch the index file nor the working tree at all (but resets the head to <commit>)
(This is great for "squashing" several commits together as they're changes are on disk and they're in the staging area (index) ready to be committed.)
--mixed
Resets the index but not the working tree (i.e., the changed files are preserved but not marked for commit) and reports what has not been updated. This is the default action.
(This is useful when you're accidentally added too much to the staging area and just want to reset it)
--hard
Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded. The Nuclear option. This is going to reset everything to be that commit. Great for when you just want to basically recreate a branch. The following will reset a branch to be the one on the Pentaho repository
git fetch upstream git reset --hard upstream/master
--merge and --keep
These are inbetween a --hard and --soft. I don't use them much, but you can read about them here (https://www.kernel.org/pub/software/scm/git/docs/git-reset.html)
Stashing
Stash is pretty intuitive. Put my changes somewhere, making it look like I've done nothing (reset to HEAD) and allow me to pull them back later. What you may not know if that you can name your stashes with the following (note: save is the default subcommand)
git stash save "My Message Here"
Reflog
Reflog is the command to see all changes to branch pointers. This will include commits, resets, etc.
Reflog can really save you if you accidently reset or rebase a branch (losing commits), or even delete a branch. Just locate the commit you know was the last in the deleted branch and issue the command to create another branch from it
git branch myRestoredBranch 724d9acd