This article explains how to perform version control using Git (Linux or Windows server) and TortoiseGit (Windows client).
Install git server and client in Ubuntu Linux:
$ sudo apt-get update $ sudo apt-get install git
Install git server and client in Windows:
Customize Git environment (Git Client) to include developer's name and email address:
$ git config --global user.name "John Doe" $ git config --global user.email "jdoe@example.com"
View the configuration:
$ git config --list
Edit the configuration:
$ vi ~/.gitconfig
D:\proj\calc
or /home/jdoe/proj/calc
D:\proj\calc\
$ cd /home/jdoe/proj/calc $ git init
[projname]/.git/info/gitattributes
or [projname]/.gitattributes
, comment out the following:#* text=auto'' #* text eol=lf
[projname]/.git/config
, add this: [core] autocrlf = false ...
$ 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
$ cp *.cs /home/jdoe/proj/calc
$ git add *.cs $ git add LICENSE.TXT
$ git commit -m "Initial repository commit"
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.[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
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.
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
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
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
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
Shelve and restore incomplete changes (see also: Git Stashing)
$ git stash [<msg>] # 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
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
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
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/<remote>/
. 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:
Get any changes in the remote branch since the last pull:
$ git fetch $ git diff ...origin (or $ git diff origin/master)
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:
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:
Install SourceTree and add BitBucket account:
Set the authentication to use Preferred Protocol SSH
instead of HTTPS
.
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
Install Private Key on Pageant (PuTTY Authentication Agent)
Add Public Key to BitBucket
Click Load and select the private key file.
Organizing your repository to use git flow. Author: Vincent Driessen | Original blog post: http://nvie.com/posts/a-succesful-git-branching-model | License: Creative Commons BY-SA