= Git Setup and Configuration = This article explains how to perform version control using Git (Linux or Windows server) and TortoiseGit (Windows client). ==Installation== Install git server and client in Ubuntu Linux: $ sudo apt-get update $ sudo apt-get install git Install git server and client in Windows: * Download server from Git: [[http://git-scm.com/downloads]] * Download client from TortoiseGit: [[https://code.google.com/p/tortoisegit/]] * Run installation for each. ==Configuration== Customize Git environment (Git Client) to include developer's name and email address: * In bash: Log in as end user (eg. jdoe), and add global configuration items: $ git config --global user.name "John Doe" $ git config --global user.email "jdoe@example.com" View the configuration:$ git config --listEdit the configuration:$ vi ~/.gitconfig * In Windows Explorer, right-click on a folder, and select "Tortoise Git" > "Settings". Enter user information (name, email). * See more: [[http://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup|First Time Git Setup]] ==Repository Setup (directory under Version Control)== * Create a directory for a project repository: Eg: For a calculator project, ''D:\proj\calc'' or ''/home/jdoe/proj/calc'' * Create Repository: * In Windows Explorer, right-click on folder to be repository. Select "TortoiseGit" > "Create Repository here". Eg: ''D:\proj\calc\'' * In bash: $ cd /home/jdoe/proj/calc $ git init * Add settings to Git (by creating [[systems:git_setup_and_configuration&#gitattributes_file|GitAttributes file]]) to avoid EOL character normalization and conversion: (IMPORTANT: Perform these steps BEFORE adding files to repository!) * In files ''[projname]/.git/info/[[#gitattributes_file|gitattributes]]'' or ''[projname]/[[#gitattributes_file|.gitattributes]]'', comment out the following:#* text=auto'' #* text eol=lf * In file ''[projname]/.git/config'', add this: [core] autocrlf = false ... * Optionally, if files were added already, reset index before adding more files: $ rm .git/index # Remove the index to force git to re-scan the working directory $ git reset # Unstage files $ git status # Show files that will be normalized $ git add -u # Only add modified content of files already being tracked (not new) $ git add .gitattributes # Add .gitattributes file to repository * Create or copy source code files to project directory. Eg: $ cp *.cs /home/jdoe/proj/calc * Stage files (begin tracking files). Add files to Git: * In Windows Explorer, right-click on project folder or file to be added to the repository. Select "TortoiseGit" > "Add". * In bash: $ git add *.cs $ git add LICENSE.TXT * Commit files to repository: * In Windows Explorer, right-click on project folder. Select 'Git commit: > "master"'. * In bash: $ git commit -m "Initial repository commit" == Setup for EOL Normalization == When adding and committing files to Git, EOL characters get normalized, ie. translated to Git's default, which is ''[LF]''. You can specify how to translate it (or not translate it at all). Git checks the ''[projname]/.gitattributes'' file first, and if nothing matches there, it drops back to the local and system wide settings, such as found in ''[projname]/.git/config''. How ''core.autocrlf'' works: core.autocrlf=true core.autocrlf=input core.autocrlf=false repo repo repo / \ / \ / \ crlf->lf lf->crlf crlf->lf \ / \ / \ / \ / \ push pull push pull push pull End-of-line marker: * ''crlf'': win-style . * ''lf'': unix-style. * ''cr'': mac-style (not affected for any of three options above). In file ''[projname]/.git/config'', under ''[core]'': * ''autocrlf = true'', if you have unix-style ''lf'' in one of your files (= RARELY). * ''autocrlf = input'', if you have win-style ''crlf'' in one of your files (= almost ALWAYS). * ''autocrlf = false'', if no EOL normalization is wanted. == GitAttributes file == * Create a file in ''[projname]/.git/info/gitattributes'', or a ''[projname]/.gitattributes'' with the following: # Define the line ending behavior of the different file extensions # Set default behaviour, in case users don't have core.autocrlf set (comment out to disable). # Auto eol normalization for text files: #* text=auto # EOL character for normalization: #* text eol=lf # Explicitly declare text files we want to always be normalized and converted # to native line endings on checkout. (Use 'text') #*.php text #*.default text #*.ctp text #*.sql text #*.md text #*.po text #*.js text #*.css text #*.ini text #*.properties text #*.txt text #*.xml text #*.yml text #.htaccess text # Disable normalization and conversion for these files (use '-text'): *.php -text *.default -text *.ctp -text *.sql -text *.md -text *.po -text *.js -text *.css -text *.ini -text *.properties -text *.txt -text *.xml -text *.yml -text .htaccess -text # Declare files that will always have CRLF line endings on checkout. *.bat eol=crlf # Declare files that will always have LF line endings on checkout. *.pem eol=lf # Denote all files that are truly binary and should not be modified. *.png binary *.jpg binary *.gif binary *.ico binary *.mo binary == Working with Git == Source: * ''[[https://training.github.com/kit/downloads/github-git-cheat-sheet.pdf|GitHub Git Cheat Sheet (PDF)]]'' * [[http://ndpsoftware.com/git-cheatsheet.html#loc=workspace;|Git CheatSheet (Interactive)]] === Create Repositories === Start a new repository or obtain one from an existing URL. $ git init [project-name] # Creates a new local repository with the specified name. $ git clone [url] # Downloads a project and its entire version history. === Make Changes === Review edits and craft a commit transaction $ git status # Lists all new or modified files to be commited $ git add [file/dir] # Snapshots the file in preparation for versioning $ git reset [file] # Unstages the file, but preserve its contents $ git diff # Shows file differences not yet staged $ git diff --staged # Shows file differences between staging and the last file version $ git commit -m "[descriptive message]" # Records file snapshots permanently in version history === Group Changes === Name a series of commits and combine completed efforts $ git branch # Lists all local branches in the current repository $ git branch [branch-name] # Creates a new branch $ git checkout [branch-name] # Switches to the specified branch and updates the working directory $ git merge [branch] # Combines the specified branch’s history into the current branch $ git branch -d [branch-name] # Deletes the specified branch === Refactor Filenames === Relocate and remove versioned files $ git rm [file] # Deletes the file from the working directory and stages the deletion $ git rm --cached [file] # Removes the file from version control but preserves the file locally $ git mv [file-original] [file-renamed] # Changes the file name and prepares it for commit === Suppress Tracking === Exclude temporary files and paths ''*.log, build/, temp-*''. A text file named ''.gitignore'' suppresses accidental versioning of files and paths matching the specified patterns. $ git ls-files --other --ignored --exclude-standard # Lists all ignored files in this project === Save Fragments (to Stash) === Shelve and restore incomplete changes (see also: [[http://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning#_git_stashing|Git Stashing]]) $ git stash [] # Temporarily stores all modified tracked files $ git stash list # Lists all stashed changesets $ git stash pop # Restores the most recently stashed files, removing top of stash $ git stash apply # Restores the most recently stashed files, without removing top of stash (no popping) $ git stash drop # Discards the most recently stashed changeset $ git stash clear # Clear stash === Review History === Browse and inspect the evolution of project files $ git log # Lists version history for the current branch $ git log --follow [file] # Lists version history for a file, including renames $ git diff [first-branch]...[second-branch] # Shows content differences between two branches $ git show [commit] # Outputs metadata and content changes of the specified commit === Redo Commits === Erase mistakes and craf replacement history $ git reset [commit] # Undoes all commits afer [commit], preserving changes locally $ git reset --hard [commit] # Discards all history and changes back to the specified commit === Synchronize Changes === Register a repository bookmark and exchange version history $ git fetch [bookmark] # Downloads all history from the repository bookmark $ git merge [bookmark]/[branch] # Combines bookmark’s branch into current local branch $ git push [alias] [branch] # Uploads all local branch commits to GitHub $ git pull # Downloads bookmark history and incorporates changes **Fetch vs. Pull:** Do a ''git fetch'' at any time to update your remote-tracking branches under ''refs/remotes//''. This operation never changes any of your own local branches under ''refs/heads''. A ''git pull'' is what you would do to bring a local branch up-to-date with its remote version, while also updating your other remote-tracking branches. Basically a ''git pull'' is a ''git fetch'' + ''git merge FETCH_HEAD'', but the latter allows time to review changes before the merge (the former does the merge automatically, which sometimes can be disastrous). Therefore, instead of a ''git pull'', using ''git fetch; git reset --hard origin/master'' is a safe method to add to your workflow. It eliminates local changes, keeps you up to date with master, but ensure new changes do not get pulled in on top on current changes and make a mess. It is a safer practice. Just be sure to add/commit/stash any work-in-progress first. See: * [[https://stackoverflow.com/questions/292357/what-is-the-difference-between-git-pull-and-git-fetch|Difference between git pull and git fetch]] * [[https://longair.net/blog/2009/04/16/git-fetch-and-merge/|Git: Fetch and Merge, Don't Pull]] Get any changes in the remote branch since the last pull: $ git fetch $ git diff ...origin (or $ git diff origin/master) === Merge or Rebase === Merge the ''master'' to the ''feature'' branch: $ git checkout feature $ git merge master Or, you can condense this to a one-liner: $ git merge master feature As an alternative to merging, you can rebase the ''feature'' branch onto ''master'' branch using the following commands: $ git checkout feature $ git rebase master The golden rule of ''git rebase'' is to never use it on public branches. For example, never rebase ''master'' onto the ''feature'' branch. This affects all developers, which causes a lot of problems. If you treat rebasing as a way to clean up and work with commits before you push them, and if you only rebase commits that have never been available publicly, then you’ll be fine. If you rebase commits that have already been pushed publicly, and people may have based work on those commits, then you may be in for some frustrating trouble, and the scorn of your teammates. FYI, you could run ''git pull --rebase'' to try to reduces issues after it happens. At this point, you can go back to the master branch and do a fast-forward merge. $ git checkout master $ git merge feature References: * [[http://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#_basic_merging|Git Basic Merging]] * [[http://git-scm.com/book/en/v2/Git-Branching-Rebasing|Git Branching and Rebasing]] * [[https://www.atlassian.com/git/tutorials/merging-vs-rebasing|Git Merging vs Rebasing]] === Remote Git Server === To have Git working as a remote backup repository, create the remote repository as a bare repository (by convention, a bare repo has ''.git'' at the end): $ mkdir my_remote_repo.git $ cd my_remote_repo.git $ git --bare init Now clone that remote repository: $ git clone [url-my_remote_repo] Now, using the new working copy, you can add files then push those files back into the remote repo. The remote location will not have a working tree. Alternatively, to turn an existing "non-bare" repository into a "bare" repository in Git, you can do this: $ git clone --bare [non-bare-repo] [new-bare-repo] You can also: * Create a bare remote repo. * Clone a local repo (populated with a working copy). * Point the new local copy to the remote repo, and push all the changes to the new remote repo. * The original local repo can now point to the remote repo (and optionally delete the local duplicate copy). == Remote Git Repositories == * [[https://bitbucket.org|BitBucket]] - Free unlimited private repositories for 5 users * [[https://github.org|GitHub]] - Free unlimited public repositories for any number of users == Setup Local Repo to Push to BitBucket Repo using SourceTree == Install SourceTree and add BitBucket account: # On the SourceTree application options (Tools > Options > Authentication > Accounts), add a BitBucket account. Set the authentication to use Preferred Protocol ''SSH'' instead of ''HTTPS''. # On the SourceTree local repo, go to Settings and change remote origin address from ''https'' (ie: ''https://[username:password]@bitbucket.org/[username]/[repo].git'') to ''ssh'' (ie: ''git@bitbucket.org:[user]/[repo].git''). You will find these addresses at the top of your BitBucket repository page. Create an SSH key # On SourceTree, select Tools > Create or Import SSH Keys. # In PuTTY Key Generator, generate a 2048-bit SSH-2 RSA key, then: * Copy the public key. * Save the private key locally. * Save the public key. Install Private Key on Pageant (PuTTY Authentication Agent) # Run Pageant or open from icon tray. # Add private SSH key, by clicking on Add Key button, then entering the passphrase. Add Public Key to BitBucket # In SourceTree, open the PuTTY Key Generator from Tools > Create or Import SSH Keys. Click Load and select the private key file. # Copy the public key. # On BitBucket Account Settings (user avatar), select SSH keys, then Add Key. # Enter label "Default Public Key". # Paste public key to Key field, and save. === References === * [[https://confluence.atlassian.com/bitbucket/set-up-an-ssh-key-728138079.html|Bitbucket: Set Up an SSH Key]] == Git Flow == Organizing your repository to use git flow. {{ :systems:git-model_2x.png?600 |}} Author: Vincent Driessen | Original blog post: http://nvie.com/posts/a-succesful-git-branching-model | License: Creative Commons BY-SA * Use Semantic Versioning: [[https://semver.org]] * [[https://nvie.com/posts/a-successful-git-branching-model/|Successful GIT branching model]] * [[https://www.youtube.com/watch?v=z53JJ7P78Vc|Git Flow Tutorial]] * [[https://blog.sourcetreeapp.com/2012/08/01/smart-branching-with-sourcetree-and-git-flow/|Smart Branching with SourceTree and Git Flow]] == References == See more: * [[http://schacon.github.io/git/gitattributes.html|GitAttributes Manual Page]] * [[http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/|Mind the end of your line]] * [[http://marklodato.github.io/visual-git-guide/index-en.html|Visual Git Guide]] * [[http://rogerdudler.github.io/git-guide|Git Guide]] * [[https://try.github.io/levels/1/challenges/1|Tutorial: Git]] * [[https://www.atlassian.com/git/tutorials/migrating-overview|Migrate to Git from SVN]]