Difference between revisions of "Git"
(→Configuration of git) |
(→Merging a branch) |
||
(6 intermediate revisions by the same user not shown) | |||
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. | ||
Line 75: | Line 82: | ||
git merge branchname | git merge branchname | ||
+ | |||
+ | == Rebasing a branch == | ||
+ | |||
+ | To go from something like this, where master has extra commits compared to a branch | ||
+ | |||
+ | * c32182bc - (HEAD -> master) Some minor cleanup from the broken code branch (3 minutes ago) | ||
+ | | * e307a930 - (broken-do-not-use-991-993) WIP #991/#993 - broken (18 hours ago) | ||
+ | | * 213ae299 - WIP #991/#993 (18 hours ago) | ||
+ | | * c3c26b92 - WIP #991 - bulk editing (18 hours ago) | ||
+ | |/ | ||
+ | * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago) | ||
+ | |||
+ | to this where the branch has all the commits from master plus copies of it's own (the commit ids change in the process) | ||
+ | |||
+ | * 50de2cba - (HEAD -> broken-do-not-use-991-993) WIP #991/#993 - broken (19 seconds ago) | ||
+ | * 8d3821db - WIP #991/#993 (3 minutes ago) | ||
+ | * de390087 - WIP #991 - bulk editing (3 minutes ago) | ||
+ | * c32182bc - (master) Some minor cleanup from the broken code branch (13 minutes ago) | ||
+ | * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago) | ||
+ | |||
+ | use the following command: | ||
+ | |||
+ | git rebase master broken-do-not-use-991-993 | ||
+ | |||
+ | Afterwards, you might want to switch back to the master branch as it'll leave you on the `broken-do-not-use-991-993` branch. | ||
== Deleting a merged branch == | == Deleting a merged branch == | ||
Line 159: | Line 191: | ||
git log --graph --oneline | git log --graph --oneline | ||
+ | |||
+ | == Rewrite author of all commits == | ||
+ | |||
+ | Committed an entire repository with the wrong email/name for the committer? Run the following to reset everything. '''Be careful!''' | ||
+ | |||
+ | git filter-branch -f --env-filter \ | ||
+ | "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \ | ||
+ | GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD | ||
+ | |||
+ | Output (for a repository with only 4 commits): | ||
+ | |||
+ | Rewrite e996a36094ba2a516dcf6bebc115f7ac25b2da6a (1/4) (0 seconds passed, remaining 0 predicted) | ||
+ | Rewrite 511aef3d14e92dbc2847934cf6313fd328aaf33d (2/4) (0 seconds passed, remaining 0 predicted) | ||
+ | Rewrite 0d6b36c9c27568161e4b4a47b2fdeefc98742379 (3/4) (0 seconds passed, remaining 0 predicted) | ||
+ | Rewrite 65b29f4418d773704e7055399c55959e45953108 (4/4) (0 seconds passed, remaining 0 predicted) | ||
+ | Ref 'refs/heads/master' was rewritten | ||
== Storing the .git directory outside the work tree == | == Storing the .git directory outside the work tree == | ||
Line 181: | Line 229: | ||
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. | 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. | ||
+ | |||
+ | == Updating git == | ||
+ | |||
+ | To update CentOS7 to the latest version 2 git, use the IUS repository. | ||
+ | |||
+ | Get the package url from https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/repoview/git2u.html and use it in the following command: | ||
+ | |||
+ | # yum install https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/git2u-2.11.1-1.ius.centos7.x86_64.rpm | ||
+ | |||
+ | If you already have the default version of git installed, you'll need to remove it first with this command: | ||
+ | |||
+ | # yum remove git perl-Git | ||
+ | |||
+ | == Aliases == | ||
+ | |||
+ | Edit ~/.gitconfig and add: | ||
+ | |||
+ | [alias] | ||
+ | lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' | ||
+ | |||
+ | or if you're the only author in this repository, you can skip the author name at the end and use this instead: | ||
+ | |||
+ | lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)' | ||
+ | |||
+ | This will cause `git lg --all` to show this kind of graph with colours for various parts of the line such as a red hash, yellow branch name and green time. | ||
+ | |||
+ | * c32182bc - (HEAD -> master) Some minor cleanup from the broken code branch (3 minutes ago) | ||
+ | | * e307a930 - (broken-do-not-use-991-993) WIP #991/#993 - broken (18 hours ago) | ||
+ | | * 213ae299 - WIP #991/#993 (18 hours ago) | ||
+ | | * c3c26b92 - WIP #991 - bulk editing (18 hours ago) | ||
+ | |/ | ||
+ | * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago) | ||
+ | * f3a6767e - Minor tidying up of code (18 hours ago) | ||
+ | * 72955241 - Code cleanup, change FIXME to TODO (3 days ago) | ||
+ | * 5a620f20 - Removed a lot of TODO (3 days ago) | ||
+ | * 53ef9e74 - Fixes #987 - file viewer default directory/filename (3 days ago) | ||
+ | * b3f37ddd - (upstream/master) Merge pull request #997 from simonamor/master (2 weeks ago) | ||
+ | |\ | ||
+ | | * 398167db - Fixes #517 - disable group if width=0 (2 weeks ago) | ||
+ | | * a3f02ec5 - Handles bottom line (2 weeks ago) | ||
+ | | * dc957aad - WIP #979 - most of the margins are handled during autoarranging now (4 months ago) | ||
+ | | * 8d060bd6 - Updated all nuget packages and target to .NET Framework 4.8 (4 months ago) | ||
+ | | * 622f3023 - Retarget everything to .NET Framework 4.8 (4 months ago) | ||
+ | |/ | ||
+ | * 684fd55f - Merge pull request #974 from simonamor/master (7 months ago) | ||
+ | |||
+ | Prevent accidental double (or more) git's from causing errors. e.g `git git status` => `git status` | ||
+ | |||
+ | git config --global alias.git '!exec git' | ||
+ | |||
+ | (or add this to your .gitconfig) | ||
+ | |||
+ | [alias] | ||
+ | git = !exec git |
Latest revision as of 09:19, 13 May 2021
Writing Good Commit Messages
There are just two rules for writing good commit messages.
- DO NOT just put "bugfix" or "updated this"
- 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
Rebasing a branch
To go from something like this, where master has extra commits compared to a branch
* c32182bc - (HEAD -> master) Some minor cleanup from the broken code branch (3 minutes ago) | * e307a930 - (broken-do-not-use-991-993) WIP #991/#993 - broken (18 hours ago) | * 213ae299 - WIP #991/#993 (18 hours ago) | * c3c26b92 - WIP #991 - bulk editing (18 hours ago) |/ * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago)
to this where the branch has all the commits from master plus copies of it's own (the commit ids change in the process)
* 50de2cba - (HEAD -> broken-do-not-use-991-993) WIP #991/#993 - broken (19 seconds ago) * 8d3821db - WIP #991/#993 (3 minutes ago) * de390087 - WIP #991 - bulk editing (3 minutes ago) * c32182bc - (master) Some minor cleanup from the broken code branch (13 minutes ago) * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago)
use the following command:
git rebase master broken-do-not-use-991-993
Afterwards, you might want to switch back to the master branch as it'll leave you on the `broken-do-not-use-991-993` branch.
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
Rewrite author of all commits
Committed an entire repository with the wrong email/name for the committer? Run the following to reset everything. Be careful!
git filter-branch -f --env-filter \ "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; \ GIT_COMMITTER_NAME='committed-name'; GIT_COMMITTER_EMAIL='committed-email';" HEAD
Output (for a repository with only 4 commits):
Rewrite e996a36094ba2a516dcf6bebc115f7ac25b2da6a (1/4) (0 seconds passed, remaining 0 predicted) Rewrite 511aef3d14e92dbc2847934cf6313fd328aaf33d (2/4) (0 seconds passed, remaining 0 predicted) Rewrite 0d6b36c9c27568161e4b4a47b2fdeefc98742379 (3/4) (0 seconds passed, remaining 0 predicted) Rewrite 65b29f4418d773704e7055399c55959e45953108 (4/4) (0 seconds passed, remaining 0 predicted) Ref 'refs/heads/master' was rewritten
Storing the .git directory outside the work tree
- content copied from http://stackoverflow.com/questions/505467/can-i-store-the-git-folder-outside-the-files-i-want-tracked
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.
Updating git
To update CentOS7 to the latest version 2 git, use the IUS repository.
Get the package url from https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/repoview/git2u.html and use it in the following command:
# yum install https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/git2u-2.11.1-1.ius.centos7.x86_64.rpm
If you already have the default version of git installed, you'll need to remove it first with this command:
# yum remove git perl-Git
Aliases
Edit ~/.gitconfig and add:
[alias] lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'
or if you're the only author in this repository, you can skip the author name at the end and use this instead:
lg = log --graph --abbrev-commit --date=relative --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)'
This will cause `git lg --all` to show this kind of graph with colours for various parts of the line such as a red hash, yellow branch name and green time.
* c32182bc - (HEAD -> master) Some minor cleanup from the broken code branch (3 minutes ago) | * e307a930 - (broken-do-not-use-991-993) WIP #991/#993 - broken (18 hours ago) | * 213ae299 - WIP #991/#993 (18 hours ago) | * c3c26b92 - WIP #991 - bulk editing (18 hours ago) |/ * e67628b3 - (origin/master, origin/HEAD) More code cleanup (18 hours ago) * f3a6767e - Minor tidying up of code (18 hours ago) * 72955241 - Code cleanup, change FIXME to TODO (3 days ago) * 5a620f20 - Removed a lot of TODO (3 days ago) * 53ef9e74 - Fixes #987 - file viewer default directory/filename (3 days ago) * b3f37ddd - (upstream/master) Merge pull request #997 from simonamor/master (2 weeks ago) |\ | * 398167db - Fixes #517 - disable group if width=0 (2 weeks ago) | * a3f02ec5 - Handles bottom line (2 weeks ago) | * dc957aad - WIP #979 - most of the margins are handled during autoarranging now (4 months ago) | * 8d060bd6 - Updated all nuget packages and target to .NET Framework 4.8 (4 months ago) | * 622f3023 - Retarget everything to .NET Framework 4.8 (4 months ago) |/ * 684fd55f - Merge pull request #974 from simonamor/master (7 months ago)
Prevent accidental double (or more) git's from causing errors. e.g `git git status` => `git status`
git config --global alias.git '!exec git'
(or add this to your .gitconfig)
[alias] git = !exec git