Git: Difference between revisions
No edit summary |
|||
(38 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{DISPLAYTITLE:git}} | |||
== Setting the initial config variables == | |||
Set user name and email address. Without <code>--global</code> parameter it will save to the current project's .<code>/.git/config</code> file.<syntaxhighlight lang="bash"> | |||
$ git config --global user.name "Joe Shmoe" | |||
$ git config --global user.email "jshmoe@domain.com" | |||
</syntaxhighlight> | |||
< | <code>push.autoSetupRemote</code> is the variable to prevent the following message for a repo that hasn't been directly pulled from the remote: | ||
git config --global user.signingkey 0A46826A | |||
</source | <syntaxhighlight lang="bash"> | ||
fatal: The current branch master has no upstream branch. | |||
To push the current branch and set the remote as upstream, use | |||
git push --set-upstream origin master | |||
To have this happen automatically for branches without a tracking | |||
upstream, see 'push.autoSetupRemote' in 'git help config'. | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="bash"> | |||
$ git config --global --add push.autoSetupRemote true | |||
</syntaxhighlight> | |||
== Signing work == | |||
Get your GPG configured, and a personal key installed. Configure Git to use your personal key. | |||
<syntaxhighlight lang="bash"> | |||
$ git config --global user.signingkey 0A46826A | |||
</syntaxhighlight> | |||
=== Signing commits === | |||
You can sign commits simply by adding -S once your environment is configured. | |||
<syntaxhighlight lang="bash"> | |||
$ git commit -S -m 'push a signed commit' | |||
</syntaxhighlight> | |||
You can check and verify via <span class="package">git log</span>: | |||
<syntaxhighlight lang="bash"> | |||
$ git log --show-signature -1 | |||
</syntaxhighlight> | |||
You can configure <span class="package">git log</span> to check any signatures and list them in output via <span class="package">%G?</span> format. | |||
<syntaxhighlight lang="bash"> | |||
$ git log --pretty="format:%h %G? %aN %s" | |||
</syntaxhighlight> | |||
You can also reject commits that are unsigned and invalid: | |||
<syntaxhighlight lang="bash"> | |||
$ git merge --verify-signature non-verify | |||
$ git merge --verify-signatures signed-branch | |||
</syntaxhighlight> | |||
Sign the merge commit itself: | |||
<syntaxhighlight lang="bash"> | |||
$ git merge --verify-signatures -S signed-branch | |||
</syntaxhighlight> | |||
== Workflows == | |||
=== Making a pull request === | |||
1. Fork the project | |||
2. Clone your fork | |||
<syntaxhighlight lang="console"> | |||
$ git clone git@gitrepo.com:mhan/forkedproject.git | |||
</syntaxhighlight> | |||
3. Set up environment to keep fork updated | |||
Set up upstream remote: | |||
<syntaxhighlight lang="console"> | |||
$ git remote add upstream git@gitrepo.com:unmit/project.git | |||
</syntaxhighlight> | |||
Update your fork: | |||
<syntaxhighlight lang="console"> | |||
$ git fetch upstream | |||
$ git branch -va | |||
$ git checkout master | |||
$ git merge upstream/master | |||
</syntaxhighlight> | |||
4. Make updates of your own | |||
Create a new branch before making any changes | |||
<syntaxhighlight lang="console"> | |||
$ git checkout master | |||
$ git branch newfeature | |||
$ git checkout newfeature | |||
</syntaxhighlight> | |||
5. Submit a pull request | |||
Rebase your development branch against upstream master branch. | |||
<syntaxhighlight lang="console"> | |||
$ git fetch upstream | |||
$ git checkout master | |||
$ git merge upstream/master | |||
$ git checkout newfeature | |||
$ git rebase master | |||
</syntaxhighlight> | |||
Squash multiple commits into fewer commits | |||
<syntaxhighlight lang="console"> | |||
$ git checkout | |||
$ git rebase -i master | |||
</syntaxhighlight> | |||
Submit | |||
* After pushing to the forked project, select development branch and click the pull request button. | |||
== Accepting and merging a pull request == | |||
== Commands == | |||
=== Add === | |||
Add only modified and deleted files: | |||
<syntaxhighlight lang="console"> | |||
$ git add -u | |||
</syntaxhighlight> | |||
=== Tags === | |||
Signing tags: | |||
<syntaxhighlight lang="bash"> | |||
$ git tag -s v2.17 -m 'version 2.17 signed by MH' | |||
$ git show v2.17 | |||
</syntaxhighlight> | |||
With the signer's public key in the keyring, you can verify the tag: | |||
<syntaxhighlight lang="bash"> | |||
$ git tag -v v2.17 | |||
</syntaxhighlight> | |||
Upload a specific tag: | |||
<syntaxhighlight lang="bash"> | |||
$ git push origin v2.29.1 | |||
</syntaxhighlight> | |||
Upload all tags: | |||
<syntaxhighlight lang="bash"> | |||
$ git push origin --tags | |||
</syntaxhighlight> | |||
Remove a tag locally | |||
<syntaxhighlight lang="bash"> | |||
$ git tag -d <tagname> | |||
</syntaxhighlight> | |||
Remove a tag on the remote repo | |||
<syntaxhighlight lang="bash"> | |||
$ git push --delete origin v0.1.8 | |||
</syntaxhighlight> | |||
Get the latest tag in the current branch | |||
<syntaxhighlight lang="console"> | |||
$ git describe --abbrev=0 --tags | |||
</syntaxhighlight> | |||
* Reference: [https://www.xspdf.com/resolution/50066178.html#:~:text=Git%20get%20latest%20tag%20on%20current%20branch&text=To%20get%20the%20latest%20annotated,%2Dmatch%20%2D%2Dabbrev%3D0. Tag-related commands] | |||
=== Clone a specific branch === | |||
<syntaxhighlight lang="bash"> | |||
$ git clone --depth 1 --single-branch -b 2.0.0 https://github.com/user/reponame.git | |||
</syntaxhighlight> | |||
=== Get a build number === | |||
A commit count can be used as a build number for a revision (e.g. HEAD, master, a commit hash): | |||
<syntaxhighlight lang="bash"> | |||
$ git rev-list --count <revision> | |||
</syntaxhighlight> | |||
To get the commit count across all branches: | |||
<syntaxhighlight lang="bash"> | |||
$ git rev-list --all --count | |||
</syntaxhighlight> | |||
To get the number of commits without merges for develop branch: | |||
<syntaxhighlight lang="bash"> | |||
$ git rev-list --no-merges --count develop | |||
</syntaxhighlight> | |||
=== Add a local branch that tracks a remote branch === | |||
<syntaxhighlight lang="bash"> | |||
$ git branch --track greet origin/greet | |||
$ git branch -a | |||
$ git merge origin/master | |||
</syntaxhighlight> | |||
=== Pulling changes from a remote === | |||
<syntaxhighlight lang="bash"> | |||
$ git fetch | |||
$ git merge origin/master | |||
</syntaxhighlight> | |||
is equivalent to: | |||
<syntaxhighlight lang="bash"> | |||
$ git pull | |||
</syntaxhighlight> | |||
=== Cleaning up remote branch list === | |||
This cleans up and removes any branches that are no longer on the remote | |||
<syntaxhighlight lang="bash"> | |||
$ git remote prune origin | |||
</syntaxhighlight> | |||
=== Rebase a branch === | |||
<syntaxhighlight lang="bash"> | |||
$ git checkout cbranch | |||
Switched to branch 'cbranch' | |||
$ git rebase master | |||
First, rewinding head to replay your work on top of it... | |||
Applying: added Greeter class | |||
Applying: hello uses Greeter | |||
Applying: updated Rakefile | |||
$ | |||
</syntaxhighlight> | |||
=== Start a new branch === | |||
<syntaxhighlight lang="console"> | |||
$ git checkout -b newbranch | |||
Switched to a new branch 'newbranch' | |||
</syntaxhighlight> | |||
=== Merge a branch === | |||
<syntaxhighlight lang="console"> | |||
$ git checkout autonotif | |||
Switched to branch 'autonotif' | |||
$ git merge <branchname> | |||
Merge made by the 'recursive' strategy. | |||
foobarrecords_savenew.hns | 1 + | |||
1 file changed, 1 insertion(+) | |||
create mode 100644 foobarrecords_savenew.hns | |||
</syntaxhighlight> | |||
Merges <branchname> onto autonotif branch | |||
=== Rename a branch === | |||
and update in the remote as well | |||
<syntaxhighlight lang="console"> | |||
$ git checkout <old_name> | |||
$ git branch -m <new_name> | |||
$ git push origin --delete <old_name> | |||
$ git push origin -u <new_name> | |||
</syntaxhighlight> | |||
=== Delete a branch === | |||
* Delete a local branch | |||
<syntaxhighlight lang="bash"> | |||
$ git branch -d hotpatch1 | |||
</syntaxhighlight> | |||
* Delete a remote branch | |||
<syntaxhighlight lang="bash"> | |||
git push origin --delete hotpatch1 | |||
</syntaxhighlight> | |||
* Delete a remote branch that as no actual reference on the remote | |||
<syntaxhighlight lang="bash"> | |||
git branch -r -d origin/hotpatch1 | |||
</syntaxhighlight> | |||
=== List merged branches === | |||
List branches merged into master | |||
<syntaxhighlight lang="bash"> | |||
$ git branch --merged master | |||
</syntaxhighlight> | |||
List branches merged into HEAD (i.e. tip of current branch) | |||
<syntaxhighlight lang="bash"> | |||
$ git branch --merged | |||
</syntaxhighlight> | |||
List branches that have not been merged | |||
<syntaxhighlight lang="bash"> | |||
$ git branch --no-merged | |||
</syntaxhighlight> | |||
=== Undo last commit === | |||
This undo is recorded as a part of the git log. | |||
<syntaxhighlight lang="bash"> | |||
$ git revert HEAD | |||
</syntaxhighlight> | |||
=== Fix or amend last commit === | |||
<syntaxhighlight lang="bash"> | |||
$ git commit --amend | |||
</syntaxhighlight> | |||
=== Undo changes to a file === | |||
<syntaxhighlight lang="bash"> | |||
$ git checkout -- filename | |||
</syntaxhighlight> | |||
=== Reset the branch to a specific point in the past === | |||
<syntaxhighlight lang="bash"> | |||
$ git reset --hard <hash> | |||
</syntaxhighlight> | |||
--hard parameter also updates the working directory. Reset shouldn't be used in a group project on a remote repository because of its potential for confusion. | |||
=== Reset the branch to a specific branch on a remote === | |||
<syntaxhighlight lang="bash"> | |||
$ git reset --hard origin/master | |||
</syntaxhighlight> | |||
=== Ignore files === | |||
;Temporary ignore changes to a file | |||
<syntaxhighlight lang="bash"> | |||
$ git update-index --assume-unchanged <filename> | |||
</syntaxhighlight> | |||
;Back to tracking changes to the file | |||
<syntaxhighlight lang="bash"> | |||
$ git update-index --no-assume-unchanged <filename> | |||
</syntaxhighlight> | |||
;Get a list of folders and files that are <code>assume-unchanged</code> | |||
<syntaxhighlight lang="bash"> | |||
$ git ls-files -v | grep '^h' | |||
</syntaxhighlight> | |||
=== Ignore file modes === | |||
This is useful when working with multiple file systems. | |||
<syntaxhighlight lang="bash"> | |||
$ git config core.filemode false | |||
</syntaxhighlight> | |||
=== Maintenance command === | |||
Verify the connectivity and validity of the objects | |||
<syntaxhighlight lang="bash"> | |||
$ git fsck --unreachable | |||
</syntaxhighlight> | |||
Manage reflog information | |||
<syntaxhighlight lang="bash"> | |||
$ git reflog expire --expire=0 --all | |||
</syntaxhighlight> | |||
Pack unpacked objects in a repository | |||
<syntaxhighlight lang="bash"> | |||
$ git repack -a -d -l | |||
</syntaxhighlight> | |||
Prune all unreachable objects from the object database | |||
<syntaxhighlight lang="bash"> | |||
$ git prune | |||
</syntaxhighlight> | |||
Clean up unnecessary files and optimize the local repository | |||
<syntaxhighlight lang="bash"> | |||
$ git gc --aggressive | |||
</syntaxhighlight> | |||
== Useful git aliases == | |||
This is a snapshot of my ~/.gitconfig | |||
<syntaxhighlight lang="ini"> | |||
[user] | |||
name = Michael Han | |||
email = mhan@pfg.fjfj.com | |||
[core] | |||
editor = vim | |||
autocrlf = input | |||
safecrlf = true | |||
[color] | |||
ui = always | |||
[alias] | |||
co = checkout | |||
ci = commit | |||
st = status | |||
br = branch | |||
df = difftool | |||
hist = log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(bold blue)[%an]\" --graph --date=short | |||
hist2 = log --graph --abbrev-commit --decorate --date=relative --format=tformat:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold blue)\" --graph --date=short | |||
histall = log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(blue)[%an]\" --graph --date=short --all | |||
hist10 = !git log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(blue)[%an]\" --graph --date=short | head -n 10 | |||
hist10all = !git log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(blue)[%an]\" --graph --date=short --all | head -n 10 | |||
listnames = diff-tree --no-commit-id --name-status -r | |||
type = cat-file -t | |||
dump = cat-file -p | |||
ignore = update-index --assume-unchanged | |||
track = update-index --no-assume-unchanged | |||
ignorelist = !git ls-files -v | grep -s ^'h ' | cut -b 1-2 --complement[diff] | |||
tool = vimdiff | |||
[difftool] | |||
prompt = false | |||
[merge] | |||
defaultToUpstream = true | |||
</syntaxhighlight> | |||
== Quick Start Guide == | |||
* [[Git - Quick Start|Using Git for collaborating on text-based data files]] | |||
== Links == | |||
;http://qugstart.com/blog/ruby-and-rails/create-a-new-git-remote-repository-from-some-local-files-or-local-git-repository/ | |||
;http://gitimmersion.com/ | |||
;http://kris.me.uk/2010/09/30/git-repository-server-gitolite.html | |||
;http://www.lucidlynx.com/how-to-install-gitweb-in-ubuntu/ | |||
;http://mustalikachwala.blogspot.com/2012/07/ubuntu-1204-installing-gitolite-and.html | |||
;http://ben.kulbertis.org/2011/10/synchronizing-a-mysql-database-with-git-and-git-hooks/ | |||
;http://viget.com/extend/backup-your-database-in-git | |||
;http://longair.net/blog/2009/04/16/git-fetch-and-merge/ | |||
:a warning against pull | |||
'http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging | |||
=== Clients === | |||
* [https://sapling-scm.com/docs/introduction/getting-started/ Sapling] | |||
**[https://engineering.fb.com/2022/11/15/open-source/sapling-source-control-scalable/ Meta engineering blog entry (2022-11)] |
Latest revision as of 18:14, 22 February 2024
Setting the initial config variables
Set user name and email address. Without --global
parameter it will save to the current project's ./.git/config
file.
$ git config --global user.name "Joe Shmoe"
$ git config --global user.email "jshmoe@domain.com"
push.autoSetupRemote
is the variable to prevent the following message for a repo that hasn't been directly pulled from the remote:
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin master
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
$ git config --global --add push.autoSetupRemote true
Signing work
Get your GPG configured, and a personal key installed. Configure Git to use your personal key.
$ git config --global user.signingkey 0A46826A
Signing commits
You can sign commits simply by adding -S once your environment is configured.
$ git commit -S -m 'push a signed commit'
You can check and verify via git log:
$ git log --show-signature -1
You can configure git log to check any signatures and list them in output via %G? format.
$ git log --pretty="format:%h %G? %aN %s"
You can also reject commits that are unsigned and invalid:
$ git merge --verify-signature non-verify
$ git merge --verify-signatures signed-branch
Sign the merge commit itself:
$ git merge --verify-signatures -S signed-branch
Workflows
Making a pull request
1. Fork the project
2. Clone your fork
$ git clone git@gitrepo.com:mhan/forkedproject.git
3. Set up environment to keep fork updated
Set up upstream remote:
$ git remote add upstream git@gitrepo.com:unmit/project.git
Update your fork:
$ git fetch upstream
$ git branch -va
$ git checkout master
$ git merge upstream/master
4. Make updates of your own
Create a new branch before making any changes
$ git checkout master
$ git branch newfeature
$ git checkout newfeature
5. Submit a pull request
Rebase your development branch against upstream master branch.
$ git fetch upstream
$ git checkout master
$ git merge upstream/master
$ git checkout newfeature
$ git rebase master
Squash multiple commits into fewer commits
$ git checkout
$ git rebase -i master
Submit
- After pushing to the forked project, select development branch and click the pull request button.
Accepting and merging a pull request
Commands
Add
Add only modified and deleted files:
$ git add -u
Tags
Signing tags:
$ git tag -s v2.17 -m 'version 2.17 signed by MH'
$ git show v2.17
With the signer's public key in the keyring, you can verify the tag:
$ git tag -v v2.17
Upload a specific tag:
$ git push origin v2.29.1
Upload all tags:
$ git push origin --tags
Remove a tag locally
$ git tag -d <tagname>
Remove a tag on the remote repo
$ git push --delete origin v0.1.8
Get the latest tag in the current branch
$ git describe --abbrev=0 --tags
- Reference: Tag-related commands
Clone a specific branch
$ git clone --depth 1 --single-branch -b 2.0.0 https://github.com/user/reponame.git
Get a build number
A commit count can be used as a build number for a revision (e.g. HEAD, master, a commit hash):
$ git rev-list --count <revision>
To get the commit count across all branches:
$ git rev-list --all --count
To get the number of commits without merges for develop branch:
$ git rev-list --no-merges --count develop
Add a local branch that tracks a remote branch
$ git branch --track greet origin/greet
$ git branch -a
$ git merge origin/master
Pulling changes from a remote
$ git fetch
$ git merge origin/master
is equivalent to:
$ git pull
Cleaning up remote branch list
This cleans up and removes any branches that are no longer on the remote
$ git remote prune origin
Rebase a branch
$ git checkout cbranch
Switched to branch 'cbranch'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added Greeter class
Applying: hello uses Greeter
Applying: updated Rakefile
$
Start a new branch
$ git checkout -b newbranch
Switched to a new branch 'newbranch'
Merge a branch
$ git checkout autonotif
Switched to branch 'autonotif'
$ git merge <branchname>
Merge made by the 'recursive' strategy.
foobarrecords_savenew.hns | 1 +
1 file changed, 1 insertion(+)
create mode 100644 foobarrecords_savenew.hns
Merges <branchname> onto autonotif branch
Rename a branch
and update in the remote as well
$ git checkout <old_name>
$ git branch -m <new_name>
$ git push origin --delete <old_name>
$ git push origin -u <new_name>
Delete a branch
- Delete a local branch
$ git branch -d hotpatch1
- Delete a remote branch
git push origin --delete hotpatch1
- Delete a remote branch that as no actual reference on the remote
git branch -r -d origin/hotpatch1
List merged branches
List branches merged into master
$ git branch --merged master
List branches merged into HEAD (i.e. tip of current branch)
$ git branch --merged
List branches that have not been merged
$ git branch --no-merged
Undo last commit
This undo is recorded as a part of the git log.
$ git revert HEAD
Fix or amend last commit
$ git commit --amend
Undo changes to a file
$ git checkout -- filename
Reset the branch to a specific point in the past
$ git reset --hard <hash>
--hard parameter also updates the working directory. Reset shouldn't be used in a group project on a remote repository because of its potential for confusion.
Reset the branch to a specific branch on a remote
$ git reset --hard origin/master
Ignore files
- Temporary ignore changes to a file
$ git update-index --assume-unchanged <filename>
- Back to tracking changes to the file
$ git update-index --no-assume-unchanged <filename>
- Get a list of folders and files that are
assume-unchanged
$ git ls-files -v | grep '^h'
Ignore file modes
This is useful when working with multiple file systems.
$ git config core.filemode false
Maintenance command
Verify the connectivity and validity of the objects
$ git fsck --unreachable
Manage reflog information
$ git reflog expire --expire=0 --all
Pack unpacked objects in a repository
$ git repack -a -d -l
Prune all unreachable objects from the object database
$ git prune
Clean up unnecessary files and optimize the local repository
$ git gc --aggressive
Useful git aliases
This is a snapshot of my ~/.gitconfig
[user]
name = Michael Han
email = mhan@pfg.fjfj.com
[core]
editor = vim
autocrlf = input
safecrlf = true
[color]
ui = always
[alias]
co = checkout
ci = commit
st = status
br = branch
df = difftool
hist = log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(bold blue)[%an]\" --graph --date=short
hist2 = log --graph --abbrev-commit --decorate --date=relative --format=tformat:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold blue)\" --graph --date=short
histall = log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(blue)[%an]\" --graph --date=short --all
hist10 = !git log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(blue)[%an]\" --graph --date=short | head -n 10
hist10all = !git log --pretty=tformat:\"%C(yellow)%h %C(green)%ad %Creset| %s%C(red)%d %C(blue)[%an]\" --graph --date=short --all | head -n 10
listnames = diff-tree --no-commit-id --name-status -r
type = cat-file -t
dump = cat-file -p
ignore = update-index --assume-unchanged
track = update-index --no-assume-unchanged
ignorelist = !git ls-files -v | grep -s ^'h ' | cut -b 1-2 --complement[diff]
tool = vimdiff
[difftool]
prompt = false
[merge]
defaultToUpstream = true
Quick Start Guide
Links
- http://longair.net/blog/2009/04/16/git-fetch-and-merge/
- a warning against pull
'http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging