Once you’ve cloned or initialized a new Git project, just start changing files as needed for your current assignment. There is no pessimistic locking of files by teammates. In fact, there’s no locking at all. Git operates in a very optimistic manner, confident that its merge capabilities are a match for any conflicted changes that you and your colleagues can craft.
If you need to move a file, Git can often detect your manual relocation of the file and will show it as a pending “move.” However, it is often more prudent to just directly tell Git to relocate a file and track its new destination.
$ git mv originalfile.txt subdir/newfilename.txt
If you wish to expunge a file from the current state of the branch, simply tell Git to remove it. It will be put in a pending deletion state and can be confirmed and completed by the next commit.
$ git rm fileyouwishtodelete.txt
Daily work calls for strong support of viewing current and historical facts about your repository, often from different, perhaps even orthogonal points of view. Git satisfies those demands in spades.
To check the current status of a project’s local directories and files (modified, new, deleted, or untracked) invoke the status command:
$ git status
A patch-style view of the difference between the currently edited and committed files, or any two points in the past can easily be summoned. The .. operator signifies a range is being provided. An omitted second element in the range implies a destination of the current committed state, also known as HEAD:
$ git diff
$ git diff 32d4
$ git diff --summary 32d4..
Depending on the Git distribution, a utility called diff-highlight will be included to make diffs easier to visualize by highlighting word-level diffs instead of the default line level changes. Make sure diff-highlight is available in your $PATH and enable it with:
$ git config --global core.pager "diff-highlight | less -r"
Git allows for diffing between the local files, the stage files, and the committed files with a great deal of precision.
|Everything unstaged (not git add’ed) diffed to the last commit
git diff –cached
|Everything staged (git add’ed) diffed to the last commit
git diff HEAD
|Everything unstaged and staged diffed to the last commit
The full list of changes since the beginning of time, or optionally, since a certain date is right at your fingertips, even when disconnected from all networks:
$ git log
$ git log --since=yesterday $ git log --since=2weeks
If trying to discover why and when a certain line was added, cut to the chase and have Git annotate each line of a source file with the name and date it was last modified:
$ git blame <filename.ext>
Git offers a useful feature for those times when your changes are in an incomplete state, you aren’t ready to commit them, and you need to temporarily return to the last committed (e.g. a fresh checkout). This feature is named “stash” and pushes all your uncommitted changes onto a stack.
$ git stash
$ git stash --include-untracked
When you are ready to write the stashed changes back into the working copies of the files, simply pop them back on the stack.
$ git stash pop
If you want to abort your current uncommitted changes and restore the working copy to the last committed state, there are two commands that will help you accomplish this.
$ git reset --hard
Resetting with the hard option recursively discards all your currently uncommitted (unstaged or staged) changes.
To target just one blob, use the checkout command to restore the file to its previous committed state.
$ git checkout -- src/main/java/com.mrasband. platform/models/Person.java
When the developer is ready to put files into the next commit, they must be first staged with the add command. Users can navigate to any directory, adding files item by item, or by wildcard.
$ git add <filename, directory name, or wildcard> $ git add submodule1/Application.java
$ git add .
$ git add *.java
Specifying a folder name as the target of a git add recursively stages files in any subdirectories.
-i option activates interactive add mode, in which Git prompts for the files to be added or excluded from the next commit.
$ git add -i
-p option is a shortcut for activation of the patch sub-mode of the interactive prompt, allowing for precise pieces within a file to be selected for staging.
$ git add -p
It’s a common use case to need to exclude some files in a project from being tracked by Git. This is supported through a .gitignore file per project that is a list of file/directory patterns to be automatically ignored. More information is available here.
$ cat .gitignore
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/. gitignore_global'
Once all the desired blobs are staged, a commit command transactionally saves the pending additions to the local repository. The default text
$EDITOR will be opened for entry of the commit message; if unset,
vi is the default.
$ git commit
Git requires that a message be present on commits, leaving the message blank will abort the commit and leave the staged blobs in place.
The default editor can be changed with a Git configuration or by setting the
$EDITOR environment variable:
$ git config --global core.editor <emacs|vim|subl --wait|atom --wait>
To supply the commit message directly at the command prompt:
$ git commit -m "<your commit message>"
To view the statistics and facts about the last commit:
$ git show
If a mistake was made in the last commit’s message, edit the commit text while leaving the changed files as-is with:
$ git commit --amend
Branching superficially appears much the same as it does in other version control systems, but the difference lies in the fact that Git branches can be targeted to exist only locally or be shared with (pushed to) the rest of the team. The concept of inexpensive local branches increases the frequency in which developers use branching, opening it up to use for quick private experiments that may be discarded if unsuccessful, or merged onto a well-known branch if successful.
$ git branch <new branch name> <from branch> $ git branch <new branch name>
Choosing a Branch
Checking out (switching to) a branch is as simple as providing its name:
$ git checkout <branch name>
Local and remote branches are checked out using the same command, but in somewhat of a radical change of operation for users coming from other systems like Subversion, remote branches are read-only until “tracked” and copied to a local branch. Local branches are where new work is performed and code is committed.
$ git branch <new branch> <from branch>
$ git checkout <new branch>
Or alternatively, in a combined command:
$ git checkout -b <new branch> <from branch>
Starting with Git 1.6.6, a shorthand notation can be used to track a remote branch with a local branch of exactly the same name when no local branch of that name already exists and only one remote location is configured.
$ git checkout <remote and local branch name>
To list the complete set of current local and remote branches known to Git:
$ get branch -a
The local branches typically have simple names like master and experiment. Local branches are shown in white by Git’s default syntax highlighting while the currently tracked branch is green with an asterisk prefix. Remote branches are prefixed by “remotes/” and are shown in red.
Like other popular VCSes, Git allows you to merge one or more branches into the current branch.
$ git merge <branch one>
$ git merge <branch one> <branch two>
If any conflicts are encountered, which is rare with Git, a notification message is displayed and the files are internally marked with
<<<<<<<< around the conflicting portion of the file contents. Once manually resolved, git-add the resolved file, then commit in the usual manner.
Rebasing is the rewinding of existing commits on a branch with the intent of moving the “branch start point” forward, then replaying the rewound commits. This allows developers to test their branch changes safely in isolation on their private branch just as if they were made on top of the mainline code, including any recent mainline bug fixes.
$ git rebase <source branch name>
$ git rebase <source branch name> <destination branch name>
$ git tag <tag name>
$ git tag <tag name> <treeish>
Automation With Hooks
Git runs a standard set of hooks during user actions. Users can define custom scripts to be run that could be utilized to interrupt actions for code quality, spell checking, testing, etc. There are samples pre-installed in .git/hooks, details are available in the Git book.