--- title: Git Ready author: geoff-doty date: 2012-10-18 template: article.jade --- Primer on Git source-control management ## Overview Git is a distributed version control system(DVAC) offering a few killer features that sway more developers towards git than any other version control system, for svn these killer features include: - speed - local commits - branching - merging SPEED: Everything in git is local, commits, logs, ignores, settings are all stored locally with in a single `.git` file. This greatly increase the speed at reading logs and reviewing commits. LOCAL COMMITS: The ability to commit, branch and stash locally allows the developer to commit without affecting other developers or the main codebase until s/he is ready to do so. This also leads to more commits providing a greater identification of the scope of work being done. BRANCHING: Branches are fast, light-weight as they are only registered as diffs from the branch your diverging. All history is local, and they can be deleted with confidence. MERGING: Merges are often looked at line-by-line, not file-by-file, so operations tend to be more like: _delete_line X_, and _add_line_X_ operations. This leads to fewer conflicts. Also if no changes have be made locally, git simply fast-forwards the codebase where merging is not required (FAST!). > Everything mentioned in this document is how **git** behaves by default. Reading through the document you may ask yourself, _"but can I do X?"_ and the answer is _almost always_ -- _"YES, there is option for that!"_ ## 1. Setup _setup operations here are one-time set-and-forget_ Introduce yourself to git git config --global user.name "Your Name" git config -- global user.email "my.email@assist-rx.com" **Line Ending Woes (`auto` | `false`)** _Different operating system use different line endings. Text editors can negotiate differences seamlessly, as can your version control system -- if you tell it to!_ In mixed environments, `false` maybe the better option, `auto`, however is a safe default`. git config --global core.autocrlf false There are other settings you may be interested in such as git config --global apply.whitespace nowarn to ignore whitespace changes. ### Handful of Commands A few git commands your going to be seeing a lot of. Command | Description |:---:|---| pull | pull commits and merges from a central/shared repo push | push commits to central/shared repo commit | commit changes locally stash | stash code for use later rebase | set [branch] as the foundation your changes are applied on top of merge | merge [branch] into the active branch ### Remotes _Spring Loops has a ssh key management system, you need to add your public key(if you have one) to the repo you want access to first_ git remote add [name] ssh://[user]@[server]/[path]/project.git > _Common practice is to name your remote 'origin'_ The first time you `push`/`pull` changes to a remote (if there is only one), you need to identify where your `push`/`pull` should go via git pull origin master after that you can just call git pull ### Clone If a git or svn repo already exists you can `clone` it which will add a remote automatically for the clone address. to clone a SVN repo into git use git svn clone @:/// _So you have code, now what?_ ## 2. Git Workflow Loop If you just cloned your repo, you can start coding, however normally you want to `pull` the latest code before you start coding. git pull Again, if you have not previously ran `pull`, you can pass the _[repo]_ and _[branch]_. __Git will let you know!__ As an example: git pull origin master Develop like only you know how! _Netbeans_, _SublimeText_, _TextMate_ -- doesn't matter. Code as you would. > __NOTE__ >> I find it best to do all code in a `branch`. As it always seems to happen if you get pulled into another project mid-step you can do so without affecting the code that you currently written. You can also `stash` your code. ee Section 3 below for more information._ When your ready to `commit` your changes, initially you'll find it similar to 'SVN'. 1. Choose the files you want to commit 2. write a `commit` message and 3. call `commit` There are a few command-line options you can pass to make this easier. git commit -m "[My Commit Message]" `-m` stands for message, and this will commit all modified files, however it will not commit new files, to do that you can pass `-a`, like this: git commit -am "[My Commit Message]" Usually you will code . . . commit . . . code . . . commit, as git lends itself better as a source control system than source backup system, however those commits are local, to share your changes you need(for central setup) to `push` them up to a `master` or central repository. > __BEFORE__ `push`, '`pull` the latest code! git pull git push Rinse and repeat! ## 3. Stash, Branch, Tag, and Merge ### Stash Git expects a clean working directory for most operations (`pull`, `push`, `rebase`), but what happens if you have files your working on, and you are not ready to commit those, but you need to `pull`, `merge`, or `rebase` your code? You `stash` them! git stash Calling the above stashes your changes and brings you to a clean state to call other commands. such as `pull`. > _New files are ignored by git until you `add` them_ When you want your stashed changes back, call git stash pop This will apply your stash on top of your current code and delete the saved stash (if successful) ​ > _Stashes are local only_ ### Tags Tag specific points in history as being important. Generally, people use this functionality to mark release points (v1.0, and so on) or otherwise known stable points in the history. git tag [tag_name] > Tag names cannot contain spaces, but you can use `.`, `-` or `_`. ### Branches Git branches are light weight code deviations (stored as _diffs_), that allow you to quickly jump and build features or try experiments without affecting your main code branch; called `master` in *git* or `trunk` in *svn*. Calling `git branch` by itself will list all the branches that exist with an asterisk(*) next to the branch your currently working in. To create a new branch you simply call git branch [name_of_branch] Then checkout your newly created `branch` via git checkout [name_of_branch] Or you can create a `branch` and `checkout` in one line via git checkout -b [name_of_branch] > REMEMBER: branches are created from the active branch Now that you've built this awesome feature in a _branch_, how do you get it back into the main project, lets say `master` for example? That's where merging comes in... ### Merging First we need to be on the `branch` that we want to `merge` changes into: git checkout master then `merge` in the changes we want with git merge [name_of_branch] If there were no conflicts, you can now remove the branch and keep you workspace clean with git branch -d [name_of_branch] The branch will be deleted **ONLY IF** the branch changes have been merged successfully. git is smart enough to only delete changes you have used, but should you want to throw away a branch use the `-D` option instead of the `-d` option to force delete the branch. ### Squash Merge (advanced) Sometimes it is advantageous to squash a series of commits in a branch when merging into another branch (such as master) to accurately convey a group of commits belong to a single feature or bug fix. git checkout master git merge --squash [name_of_branch] git commit ## Resources - [Git Homepage](http://git-scm.com/) - [Git Branches](http://gitref.org/branching/#branch)