Difference between revisions of "Git"

From Leaky
Jump to: navigation, search
(Configuration of git)
(Configuration of git: push.default behaviour)
Line 26: Line 26:
 
  git config --global color.branch auto
 
  git config --global color.branch auto
 
  git config --global diff.renamelimit 40960
 
  git config --global diff.renamelimit 40960
 +
 +
Recent versions of git will complain about the way git-push is going to work, to stop this it's recommended you use the following command. If you prefer the original behaviour for matching branches, use 'matching' instead of 'simple'
 +
 +
git config --global push.default simple
 +
 +
* '''matching''' means git push will push all your local branches to the ones with the same name on the remote. This makes it easy to accidentally push a branch you didn't intend to.
 +
* '''simple''' means git push will push only the current branch to the one that git pull would pull from, and also checks that their names match. This is a more intuitive behavior, which is why the default is getting changed to this.
  
 
If you prefer long lines to be wrapped within less, the following will fix this.
 
If you prefer long lines to be wrapped within less, the following will fix this.

Revision as of 16:11, 8 March 2016

Writing Good Commit Messages

There are just two rules for writing good commit messages.

  1. DO NOT just put "bugfix" or "updated this"
  2. Limit the commit message to approx 50 characters

Unless it is immediately obvious what was changed from the output of git diff somepath/somefile - it is always better to put things like "Bugfix - picked the wrong something for featureX" or "Updated image to reflect new pricing" to prevent someone else from having to stare at the diff output to work out what was changed.

The 50 character limit is because some of the git commands use the first line of the log message and the output will look a bit messed up if it's too long. An example of this is git log --oneline

If you can't fit everything in about 50 characters or if the commit is particularly complicated, do not use the -m option with git commit. You will be dropped into your editor of choice (most likely vi) and then can make the first line a 50 character summary of the commit, add a blank line and then any other comments that are required.

Configuration of git

The following commands should all be run from the shell.

git config --global user.name "Simon Amor"
git config --global user.email simon@leaky.org
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
git config --global diff.renamelimit 40960

Recent versions of git will complain about the way git-push is going to work, to stop this it's recommended you use the following command. If you prefer the original behaviour for matching branches, use 'matching' instead of 'simple'

git config --global push.default simple
  • matching means git push will push all your local branches to the ones with the same name on the remote. This makes it easy to accidentally push a branch you didn't intend to.
  • simple means git push will push only the current branch to the one that git pull would pull from, and also checks that their names match. This is a more intuitive behavior, which is why the default is getting changed to this.

If you prefer long lines to be wrapped within less, the following will fix this.

git config --global core.pager 'less -+$LESS -iR'

Other options you may with to add to -iR include -eFX (-e and -F are similar and relate to exiting on eof, -X doesn't initialise the terminal)

Showing all branches

Because the repository is a clone of a remote repository, you need to specify -r to the git branch command to show remote branches as well.

git branch -r

Showing remote branches and local branches

git branch -a

Comparing branches

git log has a number of options but the commonly used ones are:

  • -p will include the patch for the commit
  • --pretty=oneline returns just the sha1 and the first line of the commit message.

To find all the commits that are in one or other branch, but not in both (exclude the common ancestors)

git log master...working

This will show anything new that was added to master as well as anything new added to working

git log master..working

This will show anything new added to working that wasn't already in master

git log working..master

This will show anything new added to master that wasn't already in working

View changes in Staged files

Shows differences between HEAD and staged (added) file

git add myfile.txt
git diff --cached myfile.txt

Merging a branch

To merge branchname into the current branch, use git merge branchname - this will replay all the changes in the branch onto the current and hopefully not cause any conflicts.

git merge branchname

Deleting a merged branch

Be very careful! To remove a branch from your local repository, simply use the following to list the branches

git branch

and to remove the branch called branchname

git branch -d branchname

If it has not been merged into another branch, you might get a warning that it contains unmerged content.

In order to remove the branch from your remote repository, you need to specifically push an empty repository to that branch.

git push origin :branchname

Once it's removed from both your local and remote repositories, it most likely cannot be retrieved unless someone else fetched your remote repository and still has a copy of it!

Viewing a previous revision of a file

To view the content of a previous revision of a file without checking out that revision, use git show

git show dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/mytestscript.pl

You can also redirect the output to a file, for example if you want to revert an image rather than text.

Viewing the directory listing for a previous revision

It may be the case that after a particular revision, some files have been removed but you want to know what files were present (maybe to use git show with them to view the content).

To view the top-level directory of the repository

git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b

To view the contents of a specific path

git ls-tree dbe0e3ae9aa0a2bb29dc81450df2f7742320920b:simon/somedir/

The files listed can be viewed either using git show revision:path or git show blob-id where the blob id is the third column in the output from git ls-tree.

View creation dates of branches

git for-each-ref --sort='-authordate:iso8601' \
  --format=' %(authordate:iso8601)%09%(refname)' refs/heads

Add specific lines

git add -e filepath/filename

This will open up the differences of the file into vi, remove all changes that you don't want applied to this patch then :wq to save and apply the new add. To cancel the patch and not apply any changes delete all lines in vi and :wq

An alternative to this, if the hunks you wish to commit are separate, is to use

git add -p filepath/filename

This prompts you for each hunk whether to stage it (y), or skip it (n) - there are other options but generally these two are the only ones you'll need.

Fix half-updated dev box

git stash save
git pull
git stash apply <stashname>

Stash only specific files

Stash usually stashes all changes, to stash only certain files, git add all the files that you don't want stashed, then run

git stash --keep-index

View log for a file that has since been deleted

git log -p --follow -- full/file/path.txt

Viewing the diff ignoring whitespace changes

git diff --ignore-space-at-eol -b -w simon/mytestscript.pl

Graphical view of commits

A semi-graphical view of how the current branch has branched and merged.

git log --graph --oneline

Storing the .git directory outside the work tree

You just need to ensure that the repository knows where the work tree is and vice versa.

To let the repository know where the work tree is, set the configuration value core.worktree. To let the work tree know where it's git directory is, add a file named .git (not a folder!) and add a line like

gitdir: /path/to/repo.git

Since git 1.7.5 the init command learned an extra option for this. You can initialize a new separate repository with

git --separate-git-dir /path/to/repo.git init

This will initialize the git repository in the separate directory and add the .git file in the current directory, which is the working directory of the new repository. (Note: tried on 1.8.3 and it didn't recognise the option)

Previously to 1.7.5 you had to use slightly different parameters and add the .git file yourself. To initialize a separate repository the following command links the work-tree with the repository:

git --git-dir=/path/to/repo.git --work-tree=. init && echo "gitdir: /path/to/repo.git" > .git

Your current directory will be the working tree and git will use the repository at /path/to/repo.git. The init command will automatically set the core.worktree value as specified with the --git-dir parameter.