Git
Install
_$: apt-get install git
Configure
_$: git config --global user.name "John Doe"
_$: git config --global user.email john@example.com
Set your editor to vim
_$: git config --global core.editor "vim"
Create a new repository
_$: cd /srv/git
_$: mkdir repo
_$: git init --shared=true --bare ./repo
_$: chown --recursive root:gitgroup ./repo/
_$: chmod --recursive 2775 ./repo/ # Alternatively: g+ws
Clone a repository
Regular repository as root
# <user>@<server> <path to repository>
_$: git clone ssh://root@git.example.com/srv/git/repo
If we run this command in the /a/b
directory it will create the repository in /a/b/repo
.
Regular repository as non-root
(root@_)_$: mkdir /srv/git/repo
(root@_)_$: chown user:user ./repo
(root@_)_$: su - user
(user@_)_$: cd /srv/git/repo
(user@_)_$: git clone ssh://user@git.example.com/srv/git/repo ./
If we run this command, it will also create the repository as /a/b/repo
, but the permissions in that directory will be for the user
user, which is the one with whom we have cloned the repository.
Mirror repository
Create a mirror repository:
_$: git clone --mirror ssh://root@git.example.com/srv/git/repo
_$: chown --recursive root:gitgroup /srv/git/repo
_$: chmod 2775 /srv/git/repo # Set SGID
Update a mirror repository:
_$: git remote update
Users and groups
_$: adduser user
_$: addgroup gitgroup
_$: usermod user -aG gitgroup
Permissions
/srv/git: root:gitgroup 0770
/srv/git/repo: root:gitgroup 0770
SSH access
Generate key:
(user@workstation)_$: ssh-keygen # no passphrase only if you now what you are doing
Copy the key to the git server:
(user@workstation)_$: ssh-copy-id .ssh/id_rsa.pub user@gitserver
Remove access with password to the user:
(root@gitserver)_$: passwd -l user
Check it is possible to connect with the key:
(user@workstation)_$: ssh user@gitserver
Remove ssh access but allow the user to work with git:
(root@gitserver)_$: mkdir /home/user/git-shell-commands
(root@gitserver)_$: cp /usr/share/doc/git/contrib/git-shell-commands/list /home/user/git-shell-commands/
(root@gitserver)_$: cp /usr/share/doc/git/contrib/git-shell-commands/help /home/user/git-shell-commands/
(root@gitserver)_$: chown -R user /home/user/git-shell-commands
(root@gitserver)_$: chmod -R u+x /home/user/git-shell-commands
(root@gitserver)_$: which git-shell
/usr/bin/git-shell
(root@gitserver)_$: vipw
user:x:...:/usr/bin/git-shell
Migrate a repository
We will migrate a repository from the src
host to the dst
host:
(user@src)_$: git clone --mirror repo repo.bak
(user@src)_$: tar -cvf repo.tar repo.bak
(user@src)_$: scp repo.tar root@dst/srv/git
(user@dst)_$: tar -xvf repo.tar
(user@dst)_$: mv repo.bak repo ; rm repo.tar
(user@dst)_$: chown root:gitgroup /srv/git/repo
(user@dst)_$: chmod 0770 /srv/git
(user@dst)_$: chmod 2775 /srv/git/repo
(user@dst)_$: chmod --recursive g+w /srv/git/repo
Alternatively, we can do:
(user@dst)_$: git init --shared=true --bare repo
(user@dst)_$: ...
# See 'Create a new repository' for all steps
(user@src)_$: git remote add new_origin ssh://user@dst/srv/git/repo
(user@src)_$: git push --all new_origin
(user@src)_$: git push --tags new_origin
(user@src)_$: git remote rm origin
(user@src)_$: git remote rename new_origin origin
Change the origin path in the development host
/.../repo/.git/config:
----------------------
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = ssh://<user>@<destination>/srv/git/<repository>
[branch "master"]
remote = origin
merge = refs/heads/master
If the repository is not bare, you can also do the following:
_$: git remote add <new_repo_name> <new_repo_url>
_$: git push <new_repo_name> master
_$: git remote rm origin
_$: git push <new_repo_name> master
Repository in the development host
_$: cd /home/user/code
_$: mkdir project
_$: cd project
_$: git clone ssh://git.example.com/srv/gitdata/project/
_$: ln -s /home/user/code/project /home/user/pyvenv/project
Deployment automation
a) Force to origin/master
_$: git fetch --all
_$: git reset --hard origin/master
b) Do not force to origin/master
_$: git fetch --all
_$: git pull origin/master
Branches
Create a branch:
_$: git branch <branch>
Create a local branch that tracks a branch in origin:
_$: git checkout --track origin/<branch>
Delete a local branch:
_$: git branch -d <local_branch>
_$: git branch -D <local_branch> # Force removal even when the branch has not been updated
Delete a remote branch:
a) With the option --delete
:
_$: git push origin --delete <remote_branch>
b) Without any option:
_$: git push origin :<remote_branch>
Check in which branch we are:
_$: git branch
Change to another branch:
_$: git checkout <branch>
Set a branch which tracks a remote branch:
_$: git branch --set-upstream <branch> origin/<branch> # git 1.7
Upload a local branch to origin:
_$: git branch --set-upstream-to=origin/<branch> <branch>
Push
Push from one branch to another:
_$: git push origin <source_branch>:<destination_branch>
Merges
Up to a certain commit:
_$: git fetch
_$: git merge <sha1>
All the way:
_$: git fetch
_$: git merge origin/master
Differences
Differences between commits:
_$: git diff HEAD^ --numstat # Last commit vs HEAD
_$: git diff HEAD --numstat # Working tree (staged + unstaged) vs HEAD
_$: git diff --numstat # Working tree (staged) vs HEAD
_$: git diff --cached --numstat # Working tree (unstaged) vs HEAD
Clean a repository
_$: cd /srv/git/repo.git
_$: git gc
Update the date of the last commit
We can update the date of the last commit to the current date and time:
_$: git commit --amend --no-edit --date="$(date -R)"
If you find yourself doing this a lot, you can add it to your .bashrc
file as an alias:
.bashrc:
--------
...
alias gupdate='git commit --amend --no-edit --date="$(date -R)"'
Delete a file from the commit history
Sources:
- https://help.github.com/articles/remove-sensitive-data
- http://stackoverflow.com/questions/5563564/completely-remove-files-from-git-repo-and-remote-on-github
- http://stackoverflow.com/questions/2164581/remove-file-from-git-repository-history
- http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
_$: git filter-branch --index-filter 'git rm --cached --ignore-unmatch <file>' HEAD
_$: git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch <file>' --prune-empty --tag-name-filter cat -- --all
_$: git push origin master --force
In order for the push to work, the repository must have the fast forward enabled:
repo/.git/config:
-----------------
...
[receive]
denyNonFastforwards = false
Force the rewriting of the repo to one branch
_$: git fetch origin master # or: git fetch origin <branch>
_$: git reset --hard FETCH_HEAD
Move to a previous commit
_$: git log
...
_$: git reset ba59b4eee45e9a357e8ed26510250c40bcc5edf5 # Commit ID
Changes made
Yours (working tree) with respect to HEAD:
_$: git log @{upstream}..HEAD
_$: git diff @{upstream}..HEAD # Usual
_$: git diff --stat @{upstream}..HEAD # With statistics
_$: git diff --name-only @{upstream}..HEAD # Only filenames
HEAD with respect to yours (working tree):
_$: git log HEAD..@{upstream}
_$: git diff HEAD..@{upstream} # Unusual
_$: git diff --stat HEAD..@{upstream} # With statistics
_$: git diff --name-only HEAD..@{upstream} # Only filenames
Remember: HEAD
–> index
–> working tree
index
with respect to HEAD
:
_$: git diff --cached
working tree
with respect to index
:
_$: git diff
working tree
with respect to HEAD
:
_$: git diff HEAD
Some commit to another:
_$: git diff <oldest SHA> <newest SHA>
Some commit to another, just a file:
_$: git diff <oldest SHA> <newest SHA> -- <file>
Some commit:
_$: git show <commit SHA>
Save changes
Add a file:
_$: git add <file>
Commit changes
_$: git commit -m "Commit message explaining changes."
Push changes:
_$: git push origin master
Discard changes
Of all files in unstage
state:
_$: git clean -df && git checkout -- . # Run from the main directory
Of a file:
_$: git checkout -- </path/to/file>
Of a commit in master
already pushed:
_$: git log # Find the previous commit's SHA -> fabc72b2
_$: git reset fabc72b2 --hard # Reset to that commit
_$: git push origin +master # Force push to master
History of a deleted file
_$: git log --all -- /path/to/file