Git
Links
- Git on Wikipedia
- Git User Manual
- Git - SVN Crash Course Explaining Git by using SVN equivalences
- man gittutorial
- Git Magic tips compilation
- Git by example
- An introduction to git-svn for Subversion/SVK users and deserters
- Interfaces, frontends & tools
- Git Cheat Sheet (svg)
Install
sudo apt-get install git-svn git-doc git-gui tig
Writing to global ~/.gitconfig file:
git config --global user.name "Your Name Comes Here" git config --global user.email you@yourdomain.example.com git config --global color.diff auto git config --global color.status auto git config --global color.branch auto
Creating a .git in the current (project) directory:
git init
Working on a project
Initial project
Add manually files/directories e.g. with
git init git add . git commit
Copying existing project
Clone an existing Git repository into a to-be-created target directory:
git clone /path/to/other/repository target
Remote repositories can also be accessed with paths like
ssh://login@host/path/to/repository git://git.software.org/trunk http://git.software.org/trunk
Later to update the local repository according to the remote repository:
git pull
Symmetrically the remote repository owner could also get the changes we've done locally if she does:
git pull /path/to/our/target
Or we could send them ourselves if we've write access on the remote:
git push
BTW the remote can create a shortcut to us to not have to provide our full path everytime
git remote add ourshortcut /path/to/our/target
And now use directly
git remote show ourshortcut git pull ourshortcut
Note that git pull ourshortcut ==
git fetch ourshortcut git merge ourshortcut/master
Using a Subversion server
Using git-svn:
Getting the full project:
# git clone => git-svn clone http://subversion.server.com/project -T trunk -b branches -t tags (git-gc to compress if it took a big room)
Updating the local repository according to the subversion server:
# git pull => git-svn rebase
Some tips from here:
- While doing a rebase, if anything bad happens, you end up on a "(no-branch)" branch.
- When doing a "git status", you'll see a ".dotest" file in your working directory. Just ignore it.
- If you want to bail, do a "git rebase --abort". (Note there is no "git svn rebase --abort".)
- Fix the merge conflict file manually, then do a "git add [file]".
- Next do a "git rebase --continue". (Note there's no "svn" version of this either.)
- If it complains about "did you forget to call 'git add'?", then evidently your edit turned the conflict into a no-op change. Do a "git rebase --skip" to skip it. (Very weird, but true.)
- Rinse and repeat until the lather is gone, your scalp silky smooth, and the rebase is complete. At any time you can "git rebase --abort" to bail.
Sending the local changes to the subversion server:
# git push => git-svn dcommit
By error I did
git commit --amend
on a synchronized git repository, so I lost remotes/trunk in the gitk view but the remote branch is still visible with git branch -r, strange...
$ git-svn rebase First, rewinding head to replay your work on top of it... Nothing to do.
solved the problem
Basic usage
Edition
Schedule a file for committing
git add <file>
Committing
git commit
Note that a modified file must be explicitly added every time, unless you use
git commit -a
Or
git commit <file>
File renaming is implicit, so you don't have to take care, just rename your files if you want (really??), but there is also the explicit commands
git mv <file> git rm <file>
Diff/patch
Diff between working files & to-be-committed index
git diff
Diff between to-be-committed index & repository
git diff --cached
Diff between working files & repository
git diff HEAD
With specific revision or path
git diff <rev> <path>
E.g with one but last commit
git diff HEAD~1
This provides usage patches, including metadata, can be applied with
git apply
Status & revert
Status of local working files
git status
To restore (revert) a file from the last revision
git checkout <path>
Revert all changes (!)
git checkout -f
You can amend your latest commit (re-edit the metadata as well as update the tree) using this (it is only safe to amend the commit messages that have not been seen by anyone else, aka, you've not pushed, nobody else has pulled from you).
git commit --amend
Or toss your latest commit away completely using
git reset HEAD^
This will not change the working tree.
To unstage a change to-be-committed (e.g. git add *)
git reset HEAD <file>
History
git log
With nice stats:
git log --stat --summary
See from which revision came the lines of a file
git blame <file>
Or search for commits affecting a specific line
git log -S"string"
You can see the contents of a file
git show rev:path/to/file
The listing of a directory
git show rev:path/to/directory
Or a commit with:
git show rev
Tags & branches
Create a tag:
git tag -a <name>
List tags and show the tag message:
git tag -l git show <tag>
Create a branch:
git branch <branch> [<rev>]
Switch to the branch
git checkout <branch>
List branches (current is flagged by a *)
git branch
To move your tree to some older revision, use:
git checkout <rev> git checkout <prevbranch>
Default branch is "master"
Merge
Assuming you are in the trunk and want to merge a given branch here:
git merge branch
If the merge went nice automatically, a commit is done automatically too, to avoid it:
git merge --no-commit branch
Aside from merging, sometimes you want to just pick one commit from a different branch. To apply the changes in revision rev and commit them to the current branch use:
git cherry-pick rev
Rebase
Not yet clear what's the diff with merge...
- Find all your (committed) changes, since you branched
- Reset your branch, so that it's an exact copy of the current master
- Re-apply all your changes again
git checkout branch_name git rebase master
If conflicts occur, and sooner or later they will,
# manually edit the conflicting files git add file(s) git rebase --continue
See also "git-mergetool"
Rework commit history
You want:
- Two different commits to be combined into a single commit
- Remove a commit entirely from the history
- Change the commit message
- Change the order that commits appear in the history
- Split one big commit into multiple smaller commits
git rebase --interactive COMMIT_ID
COMMIT_ID should be the one BEFORE you want to fiddle with.
To learn about splitting a single commit up into multiple commits:
man git-rebase # see "SPLITTING COMMITS" section
Ignoring some files
cat > .gitignore <<EOF *.pyc *~ EOF git add .gitignore
Now you can also delete all files neither tracked nor ignored with:
git clean
Misc
- Revisions are SHA-1 hashes, not incremental numbers.
You can refer to the latest revision by HEAD, its parent as HEAD^ and its parent as HEAD^^ = HEAD~2
You can also just type the first digits of the hash (if it's enough to get a unique ID)
man git-rev-parse for more details - The Git commands are in the form git command. You can interchangeably use the git-command form as well.
- Setting up a public repository where you'll push your stuff
- git --bare init --shared ??
- Though not required, it's a good idea to begin the commit message with a single short (less than 50 character) line summarizing the change, followed by a blank line and then a more thorough description.
etckeeper
Description: store /etc in git, mercurial, or bzr
The etckeeper program is a tool to let /etc be stored in a git, mercurial, or bzr repository. It hooks into APT to automatically commit changes made to /etc during package upgrades. It tracks file metadata that version control systems do not normally support, but that is important for /etc, such as the permissions of /etc/shadow.
It's quite modular and configurable, while also being simple to use if you understand the basics of working with version control.
apt-get install etckeeper
Read this!!!
zless /usr/share/doc/etckeeper/README.gz
Crash course:
etckeeper init cd /etc git commit -m "initial checkin" git gc
For the rest, read /usr/share/doc/etckeeper/README.gz