User Tools

Site Tools


quickref:git

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
quickref:git [2013/06/20 16:11]
andy [Reverting Staged Files]
quickref:git [2015/07/02 11:36]
andy [Staging Files]
Line 8: Line 8:
  
 If you're not already moderately familiar with Git, strongly consider browsing the [[#Git Structure]] section first as it can make Git operations easier to understand. If you're not already moderately familiar with Git, strongly consider browsing the [[#Git Structure]] section first as it can make Git operations easier to understand.
 +
 +If you're just looking for some handy commands, check out the [[#​Recipes]] section.
  
  
Line 33: Line 35:
  
 ^ Setting ^ Default ^ Meaning ^ ^ Setting ^ Default ^ Meaning ^
 +| ''​branch.autosetupmerge''​ | ''​true''​ | As the default ''​true'',​ the "​upstream"​ of a local branch which forks off a remote branch is set to that branch. If set to ''​always''​ this behaviour is extended to include branches which fork off other local branches. If set to ''​false''​ the upstream is never automatically set. |
 | ''​color.ui''​ | ''​false''​ | Set to ''​true''​ to enable coloured output, or ''​always''​ to enable even if piping output elsewhere.\\ To apply to only some commands, replace ''​ui''​ with ''​branch'',​ ''​diff'',​ ''​interactive''​ or ''​status''​.\\ See the [[#Coloured Output]] section for details on how to customise the colours used. | | ''​color.ui''​ | ''​false''​ | Set to ''​true''​ to enable coloured output, or ''​always''​ to enable even if piping output elsewhere.\\ To apply to only some commands, replace ''​ui''​ with ''​branch'',​ ''​diff'',​ ''​interactive''​ or ''​status''​.\\ See the [[#Coloured Output]] section for details on how to customise the colours used. |
 | ''​core.excludesfile''​ | --- | Specify a global ''​.gitignore''​ file to be applied to all repositories (see [[#​.gitignore]]). | | ''​core.excludesfile''​ | --- | Specify a global ''​.gitignore''​ file to be applied to all repositories (see [[#​.gitignore]]). |
 | ''​diff.tool''​ | //varies// | Specify the tool to use for ''​git difftool'',​ either one of the pre-defined list of one defined with ''​%%difftool "​X"​.cmd%%''​. | | ''​diff.tool''​ | //varies// | Specify the tool to use for ''​git difftool'',​ either one of the pre-defined list of one defined with ''​%%difftool "​X"​.cmd%%''​. |
 | ''​merge.conflictstyle''​ | ''​merge''​ | Set to ''​diff3''​ to include common ancestor content in conflict markers. | | ''​merge.conflictstyle''​ | ''​merge''​ | Set to ''​diff3''​ to include common ancestor content in conflict markers. |
 +| ''​merge.defaultToUpstream''​ | ''​false''​ | If set to ''​true'',​ an unqualified ''​git merge''​ merges the current branch'​s "​upstream"​ in - if ''​false''​ (the default) an unqualified merge is an error. Note that an unqualified ''​git rebase''​ does merge the upstream without changing any settings (i.e. the default behaviour is inconsistent between the two commands). |
 | ''​merge.tool''​ | //varies// | Specify the tool to use for ''​git mergetool'',​ either one of the pre-defined list of one defined with ''​%%mergetool "​X"​.cmd%%''​. | | ''​merge.tool''​ | //varies// | Specify the tool to use for ''​git mergetool'',​ either one of the pre-defined list of one defined with ''​%%mergetool "​X"​.cmd%%''​. |
 +| ''​push.default''​ | ''​matching''​ | When doing a ''​git push''​ (see [[#​Pushing]]) without specifying branches on the command-line,​ by default Git attempts to push all local branches whose names match one on the remote - given that local branches can have a configured "​upstream"​ on the remote, this behaviour may seem suboptimal. Changing this setting to ''​simple''​ makes Git instead only push the current branch, and only if the branch names match //and// the remote branch is set as the upstream of the local branch. This will become the default in Git 2.0. Can also be ''​upstream''​ for the same behaviour as ''​simple''​ but without the check for matching names and ''​current''​ to match only by name but only for the current branch. The value ''​nothing''​ does nothing without an explicit branch specified on the command-line. |
 | ''​receive.denyNonFastForwards''​ | ''​false''​ | Set to ''​true''​ to disallow any non-fast-forward merges. This is often set on shared repositories to reduce the scope for losing changes. | | ''​receive.denyNonFastForwards''​ | ''​false''​ | Set to ''​true''​ to disallow any non-fast-forward merges. This is often set on shared repositories to reduce the scope for losing changes. |
 | ''​receive.denyDeletes''​ | ''​false''​ | Set to ''​true''​ to disallow deletion of any branch or tag, which may be set on shared repositories to reduce the scope of losing changes. If this is set, the only way to delete these items is to manually remove the appropriate files from the repository directory. | | ''​receive.denyDeletes''​ | ''​false''​ | Set to ''​true''​ to disallow deletion of any branch or tag, which may be set on shared repositories to reduce the scope of losing changes. If this is set, the only way to delete these items is to manually remove the appropriate files from the repository directory. |
Line 150: Line 155:
 </​file>​ </​file>​
  
-This sample output shows **six locally modified** files, ​none of which have any unstaged ​changes. Entering **''​2''​** enters the **update** mode, and then one or more files can be selected to be staged. Files can be specified in the following ways:+This sample output shows **six locally modified** files -- for example''​README.txt''​ has six lines added and four lines removed. None of the files have any **staged ​changes** however. 
 + 
 +Entering **''​2''​** enters the **update** mode, and then one or more files can be selected to be staged. Files can be specified in at least the following ways:
  
 ^ ''​3''​ | Add a single file specified by number. | ^ ''​3''​ | Add a single file specified by number. |
Line 174: Line 181:
 What now> What now>
 </​file>​ </​file>​
 +
 +Now we can see that changes have moved from the working directory into the index for those files that we've staged. If we made further modifications to the same files before committing then we'd see change summaries in both columns, since the staged files would differ from the current HEAD and the working directory copies would also differ from the staged ones.
  
 The other options perform the following functions: The other options perform the following functions:
Line 220: Line 229:
 </​code>​ </​code>​
  
-<​note ​warning>The operation of the ''​reset''​ command is subtly different if a path is not specified, so make sure you always pass the path when using it to unstage files. You can find more details about ''​git reset''​ in the [[#​Reverting Commits]] section.</​note>​+<​note ​important>The operation of the ''​reset''​ command is subtly different if a path is not specified, so make sure you always pass the path when using it to unstage files. You can find more details about ''​git reset''​ in the [[#​Reverting Commits]] section.</​note>​
  
 To revert a working file back to the state of the repository, instead use the following command: To revert a working file back to the state of the repository, instead use the following command:
Line 228: Line 237:
 </​code>​ </​code>​
  
-This is command has the potential to **destroy changes** (indeed, that's the point of it) so use with caution. This is one of the few times that Git won't warn you before overwriting a local file.+<note warning>This is command has the potential to **destroy changes** (indeed, that's the point of it) so use with caution. This is one of the few times that Git won't warn you before overwriting a local file.</​note>​
  
 ==== Committing Changes ==== ==== Committing Changes ====
Line 419: Line 428:
  
 This command takes modified files in both the working directory and the index and pushes them on to a stack of stashed files. It then reverts all these files back to their ''​HEAD''​ state, thus leaving the working directory clean. This command takes modified files in both the working directory and the index and pushes them on to a stack of stashed files. It then reverts all these files back to their ''​HEAD''​ state, thus leaving the working directory clean.
 +
 +<​note>​If you're working on a local feature branch, consider simply committing instead of stashing. You can always merge commits and change commit messages via an [[#​interactive rebase]] later. This keeps your changes attached to the appropriate branch, whereas stashed changes are "​floating"​ and may be applied to any other branch.</​note>​
  
 The example above shows that ''​git stash''​ is in fact short for ''​git stash save'',​ and using this longer form allows an optional message to be specified describing the stashed changes (similar in principle to a commit message). The example above shows that ''​git stash''​ is in fact short for ''​git stash save'',​ and using this longer form allows an optional message to be specified describing the stashed changes (similar in principle to a commit message).
  
-By default only tracked files within the repository are stashed away, leaving untracked files unchanged in the working directory. The ''​%%-u%%''​ option (or ''​%%--include-untracked%%''​) causes untracked files to also be saved away and then deleted, as with ''​[[#​Cleaning Working Directory|git clean]]''​. The ''​%%-a%%''​ option (or ''​%%--all%%''​) is similar but also includes ignored files as well.+By default only tracked files within the repository are stashed away, leaving untracked files unchanged in the working directory. The ''​%%-u%%''​ option (or ''​%%--include-untracked%%''​) causes untracked files to also be saved away and then deleted, as with ''​[[#​Cleaning Working Directory|git clean]]''​. The ''​%%-a%%''​ option (or ''​%%--all%%''​) is similar but also includes ignored files as well. As well as these inclusive options, the ''​%%--keep-index%%''​ option can be used to exclude the index, leaving any files for whom commit is pending intact and only stashing the rest.
  
-To selectively stash a subset of the local changes, use the ''​--patch''​ option to ''​save'',​ which will enter an interactive session similar to interactive adding (see [[#Staging Files]]) where the hunks to save can be selected.+To selectively stash a subset of the local changes, use the ''​%%--patch%%''​ option to ''​save'',​ which will enter an interactive session similar to interactive adding (see [[#Staging Files]]) where the hunks to save can be selected.
  
 To see the stack of stashed changes: To see the stack of stashed changes:
Line 624: Line 635:
 As with merging, if there are no conflicts during this process then the new changes are immediately committed to the repository and the branch is updated as per the diagram above. However, as you can see from the diagram it's important to note that //the ''​master''​ branch hasn't been updated// --- all that's happened is that the ''​feature-x''​ branch has had changes from ''​master''​ merged in. If further changes were to be committed to ''​master''​ at this point, the branches would fork again. Due to the rebase, however, an immediate ''​git merge''​ will perform a **fast forward** of the branch, so not require an additional merge commit. As with merging, if there are no conflicts during this process then the new changes are immediately committed to the repository and the branch is updated as per the diagram above. However, as you can see from the diagram it's important to note that //the ''​master''​ branch hasn't been updated// --- all that's happened is that the ''​feature-x''​ branch has had changes from ''​master''​ merged in. If further changes were to be committed to ''​master''​ at this point, the branches would fork again. Due to the rebase, however, an immediate ''​git merge''​ will perform a **fast forward** of the branch, so not require an additional merge commit.
  
-When doing the merge, it can be helpful to use the ''​--ff-only''​ option to make sure that the merge won't proceed unless it's a true fast forward operation.+When doing the merge, it can be helpful to use the ''​%%--ff-only%%''​ option to make sure that the merge won't proceed unless it's a true fast forward operation.
  
 <note important>​One important thing to note about rebasing is that it will discard changes where the diff appears identical to one already on the target branch. This means that the commit meta-information (author, message, etc.) of the commit on the source branch will be //​lost//​.</​note>​ <note important>​One important thing to note about rebasing is that it will discard changes where the diff appears identical to one already on the target branch. This means that the commit meta-information (author, message, etc.) of the commit on the source branch will be //​lost//​.</​note>​
  
-It's also possible to rebase on to a different branch than the parent with the ''​--onto''​ option. Consider this repository where branch ''​feature-x''​ has also had a branch created from it called ''​feature-x-y'':​+It's also possible to rebase on to a different branch than the parent with the ''​%%--onto%%''​ option. Consider this repository where branch ''​feature-x''​ has also had a branch created from it called ''​feature-x-y'':​
  
 <​graphviz>​ <​graphviz>​
Line 748: Line 759:
 </​code>​ </​code>​
  
-This will pull the specified change or changes from their own branch into the current branch. Conflicts are handled as with a standard [[#​Rebasing|rebase]] operation. If necessary this step can be repeated for other changes and then an [[#​Interactive Rebasing|interactive rebase]] performed to squash them into a single commit (or as required).+This will pull the specified change or changes from their own branch into the current branch. Conflicts are handled as with a standard [[#​Rebasing|rebase]] operation. If necessary this step can be repeated for other changes and then an [[#​Interactive Rebasing|interactive rebase]] performed ​on a parent commit ​to squash them into a single commit (or as required).
  
-The change is essentially "​copied"​ from the source branch into the destination,​ it still remains on the destination branch as well. If a later ''​git rebase''​ is performed to move the remaining changes on to the destination branch, the duplicate change will typically be detected and automatically ignored. Effectively this means that the commits may become reordered on the destination branch.+The change is essentially "​copied"​ from the source branch into the destination,​ it still remains on both branches after the operation. If a later ''​git rebase''​ is performed to move the remaining changes on to the destination branch, the duplicate change will be included in the set of changes to rebase but typically be detected and automatically ignored. Effectively this means that the commits may become reordered on the destination branch.
  
 For example, consider the following branch scenario: For example, consider the following branch scenario:
Line 802: Line 813:
 </​graphviz>​ </​graphviz>​
  
-Note that unlike a standard rebase, the destination branch ​as also been updated as with a ''​git merge''​. Now suppose a standard rebase is performed:+Note that unlike a standard rebase, the destination branch ​(''​master''​ in this case) has also been updated as with a ''​git merge''​. Now suppose a standard rebase is performed:
  
 <​code>​ <​code>​
Line 911: Line 922:
  
 Commands such as ''​git log''​ operate on a set of commits, not just a single one. To that end, the syntax for [[#single revisions]] is augmented in various ways to allow the specification of a range of commits: Commands such as ''​git log''​ operate on a set of commits, not just a single one. To that end, the syntax for [[#single revisions]] is augmented in various ways to allow the specification of a range of commits:
 +
 +<​note>​The syntax used by ''​git diff''​ appears superficially similar but is //not// the same!</​note>​
  
 ^ Method ^ Example ^ Explanation ^ ^ Method ^ Example ^ Explanation ^
Line 978: Line 991:
 <​note>​This is only a subset of the available range specifications --- see [[#Revision Ranges]] for more options.</​note>​ <​note>​This is only a subset of the available range specifications --- see [[#Revision Ranges]] for more options.</​note>​
  
-To only show commits which apply to a specified file or path, this can also be added on to the command line. Where there is any risk of being confused with a commit specification,​ it will need to be prefixed by ''​--''​ and a space (Git should terminate with an appropriate error message if there is a risk of ambiguity):+To only show commits which apply to a specified file or path, this can also be added on to the command line. Where there is any risk of being confused with a commit specification,​ it will need to be prefixed by ''​%%--%%''​ and a space (Git should terminate with an appropriate error message if there is a risk of ambiguity):
  
 <​code>​ <​code>​
Line 987: Line 1000:
  
 ^ ''​%%-<​N>​%%''​ | Show only the first ''<​N>''​ commits which would have otherwise been listed. | ^ ''​%%-<​N>​%%''​ | Show only the first ''<​N>''​ commits which would have otherwise been listed. |
-^ ''​%%--after=<​date>​%%''​ | Show only commits after the specified date, ''​--since''​ is an alias.\\ The date format is flexible and can include relative dates. | +^ ''​%%--after=<​date>​%%''​ | Show only commits after the specified date, ''​%%--since%%''​ is an alias.\\ The date format is flexible and can include relative dates. | 
-^ ''​%%--before%%''​ | Show only commits before the specified date, ''​--until''​ is an alias. |+^ ''​%%--before%%''​ | Show only commits before the specified date, ''​%%--until%%''​ is an alias. |
 ^ ''​%%--author=<​regexp>​%%''​ | Filter author field by the specified regular expression. | ^ ''​%%--author=<​regexp>​%%''​ | Filter author field by the specified regular expression. |
 ^ ''​%%--committer=<​regexp>​%%''​ | As ''​%%--author%%''​ but filters the committer field. | ^ ''​%%--committer=<​regexp>​%%''​ | As ''​%%--author%%''​ but filters the committer field. |
Line 1002: Line 1015:
 ^ ''​%%--all%%''​ | Show history of all branches, not just current one --- often used with ''​%%--graph%%''​. | ^ ''​%%--all%%''​ | Show history of all branches, not just current one --- often used with ''​%%--graph%%''​. |
 ^ ''​%%--decorate%%''​ | Annotate changes with any refs (branches, ''​HEAD'',​ etc.) that point to them. | ^ ''​%%--decorate%%''​ | Annotate changes with any refs (branches, ''​HEAD'',​ etc.) that point to them. |
-^ ''​%%--name-status%%''​ | Include the list of changed files and whether they were modified, added or deleted.\\ ''​--name-only''​ shows the same but omitting the operation.\\ The file list can be filtered with ''​%%--diff-filter%%''​. |+^ ''​%%--name-status%%''​ | Include the list of changed files and whether they were modified, added or deleted.\\ ''​%%--name-only%%''​ shows the same but omitting the operation.\\ The file list can be filtered with ''​%%--diff-filter%%''​. |
 ^ ''​%%-p%%''​ | Append the diffs introduced by the change to the entry. | ^ ''​%%-p%%''​ | Append the diffs introduced by the change to the entry. |
 ^ ''​%%--pretty=%%''//​fmt//​ | Select output format where //fmt// is ''​oneline'',​ ''​short'',​ ''​medium''​ (default), ''​full''​ or ''​fuller''​.\\ There are also additional options such as ''​format''​ to specify a ''​printf()''​-like string.\\ See the [[http://​www.kernel.org/​pub/​software/​scm/​git/​docs/​git-log.html#​_pretty_formats|git-log man page]] for more details. ​ | ^ ''​%%--pretty=%%''//​fmt//​ | Select output format where //fmt// is ''​oneline'',​ ''​short'',​ ''​medium''​ (default), ''​full''​ or ''​fuller''​.\\ There are also additional options such as ''​format''​ to specify a ''​printf()''​-like string.\\ See the [[http://​www.kernel.org/​pub/​software/​scm/​git/​docs/​git-log.html#​_pretty_formats|git-log man page]] for more details. ​ |
Line 1013: Line 1026:
 ==== git diff ==== ==== git diff ====
  
-The ''​git diff''​ command is used to show differences between files in various locations. This is similar to ''​git log''​ in some ways, although ''​git diff''​ compares the differences in the endpoints rather than examining the full commit history. As a result, ​it doesn'​t accept ​the full set of [[#Revision Ranges|ranges]] ​that ''​git log'' ​does.+The ''​git diff''​ command is used to show differences between files in various locations. This is similar to ''​git log''​ in some ways, although ''​git diff''​ compares the differences in the endpoints rather than examining the full commit history. As a result, ​while the syntax appears superficially similar ​the [[#Revision Ranges|ranges]] ​used by ''​git log''​, the interpretations differ.
  
 The possible invocations are: The possible invocations are:
  
 ^ ''​%%git diff%%''​ | Show the differences between the current working directory and the index. | ^ ''​%%git diff%%''​ | Show the differences between the current working directory and the index. |
-^ ''​%%git diff <​commit>​%%''​ | As ''​git diff'',​ but compare to the named commit instead of the index. | +^ ''​%%git diff <​commit>​%%''​ | As ''​git diff'',​ but compare ​the working directory ​to the named commit instead of the index\\ (e.g. ''​git diff HEAD''​ to compare to most recent commit on the current branch). | 
-^ ''​%%git diff --cached%%''​ | Show the differences between the index and the current HEAD.\\ Optionally, a different commit than than the HEAD can be specified. | +^ ''​%%git diff --cached ​[<​commit>​]%%''​ | Show the differences between the index and the current HEAD.\\ Optionally, a different commit than than the HEAD can be specified. | 
-^ ''​%%git diff <src-commit> <dst-commit>​%%''​\\ ''​%%git diff <src-commit>​..<​dst-commit>​%%''​ | Show differences between two arbitrary commits (the two forms are equivalent).\\ Omitting either commit causes Git to assume ''​HEAD''​. | +^ ''​%%git diff <from-commit> <to-commit>​%%''​\\ ''​%%git diff <from-commit>​..<​to-commit>​%%''​ | Show differences between two arbitrary commits (the two forms are equivalent).\\ Omitting either commit ​in the latter form causes Git to assume ''​HEAD'' ​for it. | 
-^ ''​%%git diff <src-commit>​...<​dst-commit>​%%''​ | Show differences between the common ancestor of both commits and ''<​dst-commit>''​.\\ Omitting either commit causes Git to assume ''​HEAD''​. |+^ ''​%%git diff <from-commit>​...<​to-commit>​%%''​ | Show differences between the common ancestor of both commits and ''<​to-commit>''​.\\ Omitting either commit causes Git to assume ''​HEAD''​. |
  
 As with ''​git log'',​ it's possible to supply one or more paths to filter the files diffed: As with ''​git log'',​ it's possible to supply one or more paths to filter the files diffed:
Line 1143: Line 1156:
  
 Once this file is saved, Git proceeds with the rebase as normal. Conflicts are handled as per a [[#​Rebasing|standard rebase]] and the ''​edit''​ action will also require the use of ''​%%git rebase --continue%%''​ to carry on the rebase operation. Once this file is saved, Git proceeds with the rebase as normal. Conflicts are handled as per a [[#​Rebasing|standard rebase]] and the ''​edit''​ action will also require the use of ''​%%git rebase --continue%%''​ to carry on the rebase operation.
 +
 +
 +==== Squash Merges ====
 +
 +Similar in some ways to the ''​squash''​ option of interactive rebasing is the ''​%%--squash%%''​ option to ''​git merge''​. This allows multiple commits to be merged into a single commit on a different branch. The primary difference is that an interactive rebase modifies a source branch such that the destination could be fast-forwarded to it, whereas a squashing merge will create an entirely new commit on the destination branch which is the combination of all the source commits, leaving the individual commits intact on the source branch.
 +
 +The syntax is the same as for a standard ''​git merge''​ with the addition of the ''​%%--squash%%''​ parameter. The result is that the index (only) is updated with the combination of all the source commits, so it differs from a standard merge in that this must then be committed to the repository with ''​git commit''​. In this way merges from multiple branches may be squashed together by repeated executions of ''​%%git merge --squash%%''​ prior to the ''​git commit''​. Any conflicts will be flagged and must be resolved as with a standard merge before continuing.
 +
 +Once the commit is done, the history of each source branch is left untouched and a new commit will have been created on the destination branch which is the combination of the selected commits. The source and destination branches will have effectively diverged. The situation will be something like the following example, which assumes that other commits have been made to ''​master''​ before doing the merge.
 +
 +<​graphviz>​
 +digraph G {
 +  graph [dpi=60];
 +  node [shape=box style="​filled,​rounded"​ color="​black"​ fontcolor="​black"​ fillcolor=lightgrey];​
 +  {rank="​same";​ merged -> commit7 -> commit6 -> commit3 -> commit2 -> commit1;}
 +  {rank="​same";​ commit5 -> commit4;}
 +  commit4 -> commit3;
 +  commit6 -> commit4 [style="​invis"​ weight=999];​
 +  commit7 -> commit5 [style="​invis"​ weight=999];​
 +  commit5 -> merged [style=dashed];​
 +  commit4 -> merged [style=dashed];​
 +  node [shape=box style="​filled,​rounded"​ color="​black"​ fontcolor="​black"​ fillcolor="#​eeeecc"​];​
 +  {rank="​same";​ master; "​feature-x"​}
 +  master -> merged;
 +  "​feature-x"​ -> commit5;
 +  node [shape=box style="​filled,​rounded"​ color="​black"​ fontcolor="​black"​ fillcolor="#​cceeee"​];​
 +  HEAD -> master;
 +}
 +</​graphviz>​
 +
 +As can be seen, the source branch is intact and could be left in existence as required, but unlike a rebase its commits haven'​t become part of the history of the destination branch so future merges may well produce conflicts. It's also worth noting that, unlike a standard merge, the final commit(s) on the branch(es) do //not// become parents of the mainline commit. The merged commit could have equally been created by manually applying the diffs of each source commit and an entirely new commit created.
  
 ===== Remote Repositories ===== ===== Remote Repositories =====
Line 1254: Line 1298:
 </​code>​ </​code>​
  
-The arguments may be omitted if the current branch is a **tracking branch**, and this would cause the remote ​branch tied to the current tracking branch to be used.+The arguments may be omitted if the current branch is a **tracking branch**, and this would cause the **upstream ​branch** tied to the current tracking branch to be used. To set this upstream the ''​%%git branch --set-upstream%%''​ command can be used, but often it's more convenient to specify the ''​%%-u%%''​ option to ''​git push'':​
  
-The ''<​branch>''​ specification above is actually a shorthand for the full specification:​+<​code>​ 
 +git push -u <​remote>​ <​branch>​ 
 +</​code>​ 
 + 
 +The ''<​branch>''​ specification above assumes that the branch name is the same on both repositories and is actually a shorthand for the full specification:​
  
 <​code>​ <​code>​
Line 1262: Line 1310:
 </​code>​ </​code>​
  
-The ''<​local branch>''​ here is typically a local branch, but could be any commit specification. The ''<​remote branch>''​ must be a real branch, however.+The ''<​local branch>''​ here is typically a local branch ​name, but could be any commit specification ​(e.g. a SHA1 hash). The ''<​remote branch>''​ must be a real branch, however, to avoid creation of a **detached head**, but if a non-existent branch is specified then it will be created based on the source branch. 
 + 
 +<note important>​It'​s worth noting that this point that you should avoid modifying changes (for example, via an interactive rebase) once they'​ve been pushed or pulled to another repository unless you maintain both and are prepared to deal with the resultant conflicts.</​note>​
  
 Normally the push operation fails if the remote merge operation is anything other than a **fast-forward** (i.e. the local repository has already merged all of the remote changes). If this is not the case, it will exit with an appropriate error and the remote changes will need to be merged locally first. If the branch specification is prefixed with ''​+'',​ the update will be done even if the merge is not a fast-forward. Normally the push operation fails if the remote merge operation is anything other than a **fast-forward** (i.e. the local repository has already merged all of the remote changes). If this is not the case, it will exit with an appropriate error and the remote changes will need to be merged locally first. If the branch specification is prefixed with ''​+'',​ the update will be done even if the merge is not a fast-forward.
Line 1277: Line 1327:
  
 As a special case, leaving both ''<​local branch>''​ and ''<​remote branch>''​ empty will push changes between all "​matching"​ branches --- i.e. for each local branch, a remote branch of the same name is updated if it already exists. As a special case, leaving both ''<​local branch>''​ and ''<​remote branch>''​ empty will push changes between all "​matching"​ branches --- i.e. for each local branch, a remote branch of the same name is updated if it already exists.
- 
  
 ===== Diffcore ===== ===== Diffcore =====
Line 1549: Line 1598:
 </​code>​ </​code>​
  
-This will create a directory ''​path/​in/​local/​repo''​ in the local repository and make its contents a clone of the specified remote repository'​s ''​master''​ branch. The ''​--squash''​ option squashes the history of the remote repository into a single local commit --- this is often useful for keeping the history of the local repository clean, but is entirely optional.+This will create a directory ''​path/​in/​local/​repo''​ in the local repository and make its contents a clone of the specified remote repository'​s ''​master''​ branch. The ''​%%--squash%%''​ option squashes the history of the remote repository into a single local commit --- this is often useful for keeping the history of the local repository clean, but is entirely optional.
  
 To later merge changes from the remote repository into the local one: To later merge changes from the remote repository into the local one:
Line 1569: Line 1618:
 </​code>​ </​code>​
  
-This creates a synthetic set of commits which are the filtered versions of those affecting the subtree in the repository. With the ''​--branch''​ option it also creates a new branch to track the head of this synthetic commit history.+This creates a synthetic set of commits which are the filtered versions of those affecting the subtree in the repository. With the ''​%%--branch%%''​ option it also creates a new branch to track the head of this synthetic commit history.
  
 <​note>​The commits are identical across multiple split operations, so repeated splits can be used without risk of duplicating commits.</​note>​ <​note>​The commits are identical across multiple split operations, so repeated splits can be used without risk of duplicating commits.</​note>​
Line 1934: Line 1983:
 ^ ''​hooks/''​ | Client- or server-side hook scripts. | ^ ''​hooks/''​ | Client- or server-side hook scripts. |
 ^ ''​index/''​ | Where staging area information is stored. | ^ ''​index/''​ | Where staging area information is stored. |
-^ ''​info/''​ | global exclusions file for those which shouldn'​t be tracked in ''​.gitignore''​. |+^ ''​info/''​ | Contains a global exclusions file for those which shouldn'​t be tracked in ''​.gitignore''​. |
 ^ ''​objects/''​ | Where the actual repository content is stored (file content, commit objects, etc.). | ^ ''​objects/''​ | Where the actual repository content is stored (file content, commit objects, etc.). |
 ^ ''​refs/''​ | Pointers to commit objects in the object store. | ^ ''​refs/''​ | Pointers to commit objects in the object store. |
Line 1986: Line 2035:
  
 <file - .gitconfig>​ <file - .gitconfig>​
-[user] +        ​name = Andy Pearce
- name = Andy Pearce +
- email = andy@andy-pearce.com+
 [merge] [merge]
- conflictstyle ​diff3 +        tool vimdiff 
- tool meld+        ​defaultToUpstream ​true
 [diff] [diff]
- tool = meld+        ​tool = vimdiff
 [color] [color]
- ui = true+        ​ui = true
 [color "​branch"​] [color "​branch"​]
- current = green bold +        ​current = green bold 
- local = green +        local = green 
- remote = blue +        remote = black bold 
- plain = red+        plain = red
 [color "​diff"​] [color "​diff"​]
- plain = white +        ​plain = white 
- meta = white blue bold +        meta = yellow ​blue bold 
- frag = blue bold +        frag = white blue bold 
- func = blue bold +        func = white blue 
- old = red bold +        old = red 
- new = green bold +        new = green 
- commit = white bold +        commit = yellow 
- whitespace = white red+        whitespace = red reverse
 [color "​decorate"​] [color "​decorate"​]
- branch = green +        ​branch = green 
- remoteBranch = blue +        remoteBranch = black bold 
- tag = red +        tag = red 
- stash = cyan +        stash = blue bold 
- HEAD = yellow+        HEAD = yellow ​bold
 [color "​grep"​] [color "​grep"​]
- context = cyan +        ​context = cyan 
- filename = magenta +        filename = magenta 
- function = white blue bold +        function = white blue bold 
- linenumber = green +        linenumber = green 
- match = yellow bold +        match = yellow bold 
- selected = white +        selected = white 
- separator = cyan+        separator = cyan
 [color "​interactive"​] [color "​interactive"​]
- prompt = white bold +        ​prompt = white bold 
- header = blue bold +        header = blue bold 
- help = green +        help = green 
- error = red bold+        error = red bold
 [color "​status"​] [color "​status"​]
- header = blue bold +        ​header = blue bold 
- added = green +        added = green 
- updated = green +        updated = green 
- changed = red bold +        changed = red bold 
- untracked = cyan +        untracked = cyan 
- branch = green bold +        branch = green bold 
- nobranch = white red bold+        nobranch = white red bold 
 +[init] 
 +        templatedir = /​home/​apearce16/​.git_template 
 +[alias] 
 +        aliases = "!git config --list | grep ^alias"​ 
 +        branches = for-each-ref --sort=-committerdate --format='​%(color:​cyan)|%(committerdate:​relative)| %(color:​yellow bold)%(refname:​short)'​ refs/​heads 
 +        branchgraph = log --graph --abbrev-commit --decorate --simplify-by-decoration --date=relative --all --pretty=format:"​%C(yellow)%h\\ %C(cyan)|%ad|%C(yellow)%C(bold)%d\\ %Creset%s%C(green)\\ [%an]%C(blue)%C(bold)\\ <​%cn>"​ 
 +        branchhistory = "!git showline HEAD; git showline @{-1}; git showline @{-2}; git showline @{-3}; git showline @{-4}; git showline @{-5}"​ 
 +        changed = diff-tree -r --no-commit-id --name-only --relative 
 +        changes = log --pretty=format:"​%C(yellow)%h\\ %C(cyan)|%ad|%C(yellow)%C(bold)%d\\ %Creset%s%C(green)\\ [%an]%C(blue)%C(bold)\\ <​%cn>"​ --decorate --stat --date=relative 
 +        commits = log --pretty=format:"​%C(yellow)%h\\ %C(cyan)|%ad|%C(yellow)%C(bold)%d\\ %Creset%s%C(green)\\ [%an]%C(blue)%C(bold)\\ <​%cn>"​ --decorate --date=relative 
 +        ctags = !.git/​hooks/​ctags 
 +        fe = fetch --prune 
 +        ff = merge --ff-only 
 +        graph = log --graph --abbrev-commit --decorate --date=relative --all --pretty=format:"​%C(yellow)%h\\ %C(cyan)|%ad|%C(yellow)%C(bold)%d\\ %Creset%s%C(green)\\ [%an]%C(blue)%C(bold)\\ <​%cn>"​ 
 +        grepall = "!git grep --full-name -n -p" 
 +        showline = log --oneline --decorate -1 
 +        summary = show --name-status 
 +[push] 
 +        default = upstream 
 +[rebase] 
 +        autosquash = true 
 + 
 +[difftool] 
 +        prompt = false
 </​file>​ </​file>​
  
Line 2052: Line 2123:
 </​file>​ </​file>​
  
 +===== Recipes =====
 +
 +The following are some handy pre-canned commands for specific situations. You can set up [[https://​git.wiki.kernel.org/​index.php/​Aliases|aliases]] for these as well.
 +
 +==== Housekeeping ====
 +
 +A good couple of aliases to run in quick succession to fetch remotes with pruning, and then fast-forward the current branch if possible:
 +
 +<​code>​
 +git fetch --prune
 +git merge --ff-only
 +</​code>​
 +
 +
 +==== Searching ====
 +
 +Search the entire repository, regardless of the current subdirectory:​
 +
 +<​code>​
 +git grep --full-name -n -p <​needle>​
 +</​code>​
 +
 +
 +==== Listing commits ====
 +
 +Show recent commits with relative dates and authors:
 +
 +<​code>​
 +git log --decorate --date=relative \
 +        --pretty=format:"​%C(yellow)%h %C(cyan)|%ad|%C(yellow)%C(bold)%d %Creset%s%C(green) [%an]%C(blue)%C(bold) <​%cn>"​
 +</​code>​
 +
 +Show the history of a specified file:
 +
 +<​code>​
 +git log -p -- <​filename>​
 +</​code>​
 +
 +Show a graph of all commits:
 +
 +<​code>​
 +git log --graph --abbrev-commit --decorate --date=relative --all \
 +        --pretty=format:"​%C(yellow)%h %C(cyan)|%ad|%C(yellow)%C(bold)%d %Creset%s%C(green) [%an]%C(blue)%C(bold) <​%cn>"​
 +</​code>​
 +
 +As above, but only commits which are the head of a branch:
 +
 +<​code>​
 +git log --pretty=format:"​%C(yellow)%h %C(cyan)|%ad|%C(yellow)%C(bold)%d %Creset%s%C(green) [%an]%C(blue)%C(bold) <​%cn>"​ \
 +        --graph --abbrev-commit --decorate --simplify-by-decoration --date=relative --all 
 +</​code>​
 +
 +
 +==== Listing Files ====
 +
 +Show files that changed between two commits in the current directory:
 +
 +<​code>​
 +git diff-tree -r --no-commit-id --name-only --relative <​commit1>​ <​commit2>​
 +</​code>​
 +
 +
 +==== Listing Branches ====
 +
 +List branches in order of last commit time, most recent first (useful for removing dead branches):
 +
 +<​code>​
 +git for-each-ref --sort=-committerdate \
 +                 ​--format='​%(color:​cyan)|%(committerdate:​relative)| %(color:​yellow bold)%(refname:​short)'​ \
 +                 ​refs/​heads
 +</​code>​
  
quickref/git.txt · Last modified: 2015/07/02 11:36 by andy