Git的基本命令
Git真正是一个面向程序员的工具,它的内部数据结构是一个有向无环图,并且,你必须理解它的内部数据结构后,才能掌握它。因为你的很多操作,都其实对应的是这个有向无环图的操作。比如:
git commit就是增加一个结点。 git commit –amend就是改前一个结点。 git reset就是修改HEAD指向的结点。
另外,Git内部包括三个区域:工作区,暂存区和版本库。
git add 是将工作区的内容保存到暂存区 git checkout 是将暂存区的内容覆盖工作区 git commit 是将暂存区的内容保存到版本库 git reset 默认情况下是将版本库的内容覆盖工作区 git diff 也有三种情况,分别是比较工作区与暂存区,工作区与版本库,暂存区与版本库之间的差别
了解了Git的内部结构,对于这些Git的命令就更加理解了。
Git的坑
在windows下的文件的权限因为无法和linux上完全一致,所以用Git检出的文件权限可能显示为被更改。 另外因为windows下的换行和linux上也不一样,协作开发时也容易出问题。所以在windows上使用Git的同学需要加上以下2行配置参数:
git config --global core.filemode false git config --global core.autocrlf true
第一句是忽略文件权限的改动。
第二句是将文件checkout时自动把LF转成CRLF,check in 时自动把CRLF转成LF
强制推送
一旦推送到远程仓库后,就不要用类似git reset, git commit –-amend, git rebase等破坏性提交了,否则远程仓库会因为你的新推送不是Fast Forward而拒绝提交(关于什么是Fast Forward要讲的太多了,自已看书吧)。如果实在不小心做了。在确定别人没有检出前,用git push -f
可以强制推送到远程仓库中。
强制上传的命令
git push --force [远程名] [本地分支名]:[远程分支名]
例如
git push origin master --force
删除不在git管理下的文件
如果你需要删除Git下没有加入到版本库中的文件,可以使用:
git clean -nd 测试删除 git clean -fd 真实删除
搭建自己的远程仓库
搭建一个Git远程仓库相当简单,直接在一台带SSH的服务器上用git init –bare dirname即可。本地可以用git remote命令来设置多个远程分支。另外,第一次提交的时候,因为远程仓库中没有任何分支,需要用如下指令建立master分支:
git remote add origin yourname@yourhost.com:~/path/repository_name git remote add add2 yourname@yourhost.com:~/path/repository_name git push origin master git push add2 master
// 如果git remote add设置地址写错了,可以用git remote set-url更改:
git remote set-url origin yourname@yourhost.com:~/path/repository_name
如何用Git将一个文件的历史提交恢复?
上次遇到一个问题,我某次提交改动了很多文件,但是其中有一个是不应该改的。所以我需要把这次提交中关于那个文件的改动撤销。直接用git checkout命令可以检出某一个文件的历史版本,然后就可以将对这个文件的改动取消了。如下:
git checkout CommitId fileName git ci -m "revert a file modification"
本地工作区还有未提交的内容时,不能pull?
可以先用 git stash 将内容暂存,然后再pull,成功后再git stash pop将修改恢复。
提交的邮箱错了?
有些时候,因为同时在github和公司内部做提交,所以用2个不同的邮箱。如果一个新工程clone下来,忘了用git config 来设置提交用户名和邮箱,就有可能用错误的邮箱作为账号名提交。这个时候,如果你只是错了最近的一次提交而已,可以用如下命令来将最近的一次提交作者名和邮箱修改:
git config user.email your-email@163.com git config user.name your-name git commit --amend --reset-author
如果等你发现的时候,已经错了很多提交了。可以用如下命令来一次性修改多个提交的用户名和邮箱:
git filter-branch -f --env-filter " GIT_AUTHOR_NAME='your-name' GIT_AUTHOR_EMAIL='your-email@163.com' GIT_COMMITTER_NAME='your-name' GIT_COMMITTER_EMAIL='your-email@163.com' " HEAD
提交的时候自动去掉源码末尾的空格
源码末尾的空格几乎都是无意义的,应该去掉的。大多数review系统,都会将源码末尾的空格标红。所以,我们何不在提交时让git自动帮我们去掉这些空格呢?这个可以通过设置git的hook来实现,具体方法如下:
用vim编辑一个名为pre-commit的文件:
vim .git/hooks/pre-commit
输入如下代码,保存退出vim
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/bin/sh if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # Find files with trailing whitespace for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -E 's/:[0-9]+:.*//' | uniq` ; do # Fix them! sed -i '' -E 's/[[:space:]]*$//' "$FILE" git add "$FILE" done |
增加pre-commit的运行权根:
chmod +x .git/hooks/pre-commit
让常用操作自动带颜色
默认的git diff, status, log什么的都是不带颜色的,可以用如下命令让它们都带上颜色。另外还有一些有趣的命令,一并列在下面。
git config --global --add user.email "email@163.com" git config --global --add user.name "your name" git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status -s git config --global alias.l log --oneline --decorate -12 git config --global color.diff auto git config --global color.status auto git config --global color.branch auto git config --global merge.tool kdiff3 git config --global meregtool.kdiff3.path "/usr/bin/kdiff3" git config --global alias.visual "!gitk"
自动补全git命令
-
安装bash-completion:
brew install bash-completion
-
按要求把以下代码增加到 .bash_profile文件中:
if [ -f `brew --prefix`/etc/bash_completion ]; then . `brew --prefix`/etc/bash_completion fi
-
下载bash-completion对于Git的支持
cd /usr/local/etc/bash_completion.d/ sudo curl -O https://raw.github.com/git/git/master/contrib/completion/git-completion.bash
配置别名
有没有经常敲错命令?比如git status?status这个单词真心不好记。
如果敲git st就表示git status那就简单多了,当然这种偷懒的办法我们是极力赞成的。
我们只需要敲一行命令,告诉Git,以后st就表示status:
git config --global alias.st status
好了,现在敲git st看看效果。
当然还有别的命令可以简写,很多人都用co表示checkout,ci表示commit,br表示branch:
git config --global alias.co checkout git config --global alias.ci commit git config --global alias.br branch
以后提交就可以简写成:
git ci -m "bala bala bala..."
--global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。
命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区。既然是一个unstage操作,就可以配置一个unstage别名:
git config --global alias.unstage 'reset HEAD'
当你敲入命令:
git unstage test.py
实际上Git执行的是:
git reset HEAD test.py
配置一个git last,让其显示最后一次提交信息:
git config --global alias.last 'log -1'
这样,用git last就能显示最近一次的提交:
git last commit adca45d317e6d8a4b23f9811c3d7b7f0f180bfe2 Merge: bd6ae48 291bea8 Author: Michael Liao <askxuefeng@gmail.com> Date: Thu Aug 22 22:49:22 2013 +0800 merge & fix hello.py
甚至还有人丧心病狂地把lg配置成了:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
修改commit
修改最近一次commit
commit提供了一个--amend
参数,可以修改最后一次提交的信息,但是如果你已经push
过了,那么其历史最后一次,永远也不能修改了。
# git commit --amend
然后在出来的编辑界面,直接编辑注释
的信息。。
修改历史提交
git使用amend选项提供了最后一次commit的反悔。但是对于历史提交呢,就必须使用rebase了。
git rebase -i HEAD~3
表示要修改当前版本的倒数第三次状态。
这个命令出来之后,会出来三行东东:
pick:******* pick:******* pick:*******
如果你要修改哪个,就把那行的pick改成edit,然后退出。
这时通过git log
你可以发现,git的最后一次提交已经变成你选的那个了,这时再使用:
git commit --amend
来对commit进行修改。
修改完了之后,要回来对不对?
git rebase --continue
OK,一切都搞定了。
合并分支
git rebase -i HEAD~5 //最后五次
显示结果如下,修改第二到第五个 pick
为 s
,并 :wq 保存退出
pick 92b495b 2009-08-08: ××××××× pick 92b423b 2009-08-08: ××××××× pick 92b489b 2009-08-08: ××××××× pick 92b428b 2009-08-08: ××××××× pick 92b409b 2009-08-08: ×××××××
相关资源
Rebasing http://magazine.joomla.org/issues/Issue-Nov-2011/item/586-Rebasing