- 查看历史记录
git log用于查询版本的历史,命令形式如下:
git log [<options>] [<since>..<until>] [[–] <path>…]
- 不带参数
[root@centos6 ekwing]# git log
commit 6d7147bfc5a2e1a40fc3355548f0ffbf7d3e4935
Author: ekcr <ekcr@moyi365.com> #提交用户
Date: Wed Aug 8 01:18:13 2018 +0800 #提交日期
2018-08-08_01:18:12 #提交说明
……
如果不带任何参数,它会列出所有历史记录,最近的排在最上方,显示提交对象的哈希值,作者、提交日期、和提交说明。
如果记录过多,则按Page Up、Page Down、↓、↑来控制显示。按q退出历史记录列表
- 显示参数
- -p:按补丁显示每个更新间的差异,比下一条- -stat命令信息更全
- –stat:显示每次更新的修改文件的统计信息,每个提交都列出了修改过的文件,以及其中添加和移除的行数,并在最后列出所有增减行数小计
- –shortstat:只显示–stat中最后的行数添加修改删除统计
- –name-only:尽在已修改的提交信息后显示文件清单
- –name-status:显示新增、修改和删除的文件清单
- –abbrev-commit:仅显示SHA-1的前几个字符,而非所有的40个字符
- –relative-date:使用较短的相对时间显示(例如:”two weeks ago”)
- –graph:显示ASCII图形表示的分支合并历史
- —pretty=:使用其他格式显示历史提交信息,可选项有:oneline,short,medium,full,fuller,email,raw以及format:
–pretty=oneline:一行显示,只显示哈希值和提交说明(–online本身也可以作为单独的属性)
–pretty=format:” “:控制显示的记录格式,如:
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 -date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期(可以用 -date= 选项定制格式)
%cr 提交日期,按多久以前的方式显示
%s 提交说明
- –date= (relative|local|default|iso|rfc|short|raw):定制后边如果出现%ad或%cd时的日期格式
- 筛选参数
- 按数量
-n:显示前n条log
- 按日期
–after=
- 比如git log –after=”2014-7-1”,显示2014年7月1号之后的commit(包含7月1号)
- 后边的日期还可以用相对时间表示,比如”1 week ago”和”yesterday”,比如git log –after=”yesterday”
–before=
- 同上
另外这两条命令可以同时使用表示时间段,比如git log –after=”2014-7-1″ –before=”2014-7-4″。另外–since –until和 –after –before是一个意思,都可以用
- 按作者
–author=
- 比如git log –author=”John”,显示John贡献的commit
- 注意:作者名不需要精确匹配,只需要包含就行了。而且:可以使用正则表达式,比如git log –author=”John\|Mary”,搜索Marry和John贡献的commit
- 而且:这个–author不仅包含名还包含email, 所以你可以用这个搜索email
- 按commit描述
–grep=
- 比如:git log –grep=”JRA-224″
- 而且:可以传入-i用来忽略大小写
- 注意:如果想同时使用–grep和–author,必须在附加一个–all-match参数
- 按文件
– -(空格)或[没有]
- 有时你可能只对某个文件的修改感兴趣, 你只想查看跟某个文件相关的历史信息, 你只需要插入你感兴趣文件的路径就可以了。比如:git log — foo.py bar.py ,只返回和foo.py或bar.py相关的commit
- 这里的–是告诉Git后面的参数是文件路径而不是branch的名字. 如果后面的文件路径不会和某个branch产生混淆, 你可以省略–,比如git log foo.py
- 另外,后边的路径还支持正则,比如:git log *install.md 是,指定项目路径下的所有以install.md结尾的文件的提交历史
- 另外,文件名应该放到参数的最后位置,通常在前面加上–并用空格隔开表示是文件
- 另外,git log file/ 查看file文件夹下所有文件的提交记录
- 按commit
- git log commit :查询commit之前的记录,包含commit
- git log commit1 commit2:查询commit1与commit2之间的记录,包括commit1和commit2
- git log commit1..commit2:同上,但是不包括commit1
其中,commit可以是提交哈希值的简写模式,也可以使用HEAD代替。HEAD代表最后一次提交,HEAD^为最后一个提交的父提交,等同于HEAD~1。HEAD~2代表倒数第二次提交
- 按范围
git log <since>..<until>
这个命令可以查看某个范围的commit。当你使用branch做为range参数的时候. 能很方便的显示2个branch之间的不同。
比如:git log master..feature,master..feature这个range包含了在feature有而在master没有的所有commit,同样,如果是feature..master包含所有master有但是feature没有的commit
另外,如果是三个点,表示或的意思:git log master…test 查询master或test分支中的提交记录
- Git diff
用于比较两次修改的差异。
git diff #不加参数即默认比较工作区与暂存区
git diff –cached [<path>…] #比较暂存区与最新本地版本库
git diff HEAD [<path>…] #比较工作区与最新本地版本库
git diff commit-id [<path>…] #比较工作区与指定commit-id的差异
git diff –cached [<commit-id>] [<path>…] #比较暂存区与指定commit-id的差异
git diff [<commit-id>] [<commit-id>] #比较两个commit-id之间的差异
git diff origin/master master
git log –pretty=oneline –name-status
git log 5fb7d5d74ab35a –pretty=oneline –name-status -n 1
git pull origin master
git push origin master:master
git log origin/master –pretty=oneline –name-status
git reset –hard origin/master
git fetch origin master:tmp
//在本地新建一个temp分支,并将远程origin仓库的master分支代码下载到本地temp分支
git diff tmp
//来比较本地代码与刚刚从远程下载下来的代码的区别
- origin和master解析
对git的操作是围绕3个大的步骤来展开的
- 从git取数据(git clone)
- 改动代码
- 将改动传回git(git push)
这3个步骤又涉及到两个repository,一个是remote repository,再远程服务器上,一个是local repository,再自己工作区上。其中1, 3两个步骤涉及到remote server/remote repository/remote branch
2涉及到local repository/local branch。git clone 会根据你指定的remote server/repository/branch,拷贝一个副本到你本地,再git push之前,你对所有文件的改动都是在你自己本地的local repository来做的,你的改动(local branch)和remote branch是独立(并行)的。Gitk显示的就是local repository。
- git clone解析
在clone完成之后,Git 会自动为你将此远程仓库命名为origin(origin只相当于一个别名,运行git remote -v或者查看.git/config可以看到origin的含义。即origin是代表远程仓库的一个默认别名, 可以在项目工程目录中.git/config文件中查看或修改),并下载其中所有的数据,建立一个指向它的master 分支的指针,我们用(远程仓库名)/(分支名) 这样的形式表示远程分支,所以origin/master指向的是一个remote branch(从那个branch我们clone数据到本地),但你无法在本地更改其数据。
同时,Git 会建立一个属于你自己的本地master 分支,它指向的是你刚刚从remote server传到你本地的副本。随着你不断的改动文件,git add, git commit,master的指向会自动移动,你也可以通过merge(fast forward)来移动master的指向。
- git branch解析
$git branch -a #to show all the branches git knows about
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
$git branch -r #to show remote branches git knows about
origin/HEAD -> origin/master
origin/master
可以发现,master就是local branch,origin/master是remote branch(master is a branch in the local repository. remotes/origin/master is a branch named master on the remote named origin)
$git diff origin/master master #查看远程主分支与本地主分支的区别
需要注意的是,remotes/origin/master和origin/master的指向是相同的
- git push解析
$git push origin master
origin指定了你要push到哪个remote
master其实是一个“refspec”,正常的“refspec”的形式为”+<src>:<dst>”,冒号前表示local branch的名字,冒号后表示remote repository下 branch的名字。注意,如果你省略了<dst>,git就认为你想push到remote repository下和local branch相同名字的branch。听起来有点拗口,再解释下,push是怎么个push法,就是把本地branch指向的commit push到remote repository下的branch,比如
$git push origin master:master
解释:在local repository中找到名字为master的branch,使用它去更新remote repository下名字为master的branch,如果remote repository下不存在名字是master的branch,那么新建一个
其他示例解释:
$git push origin master #(省略了<dst>,等价于“git push origin master:master”)
$git push origin master:refs/for/mybranch #(在local repository中找到名字为master的branch,用他去更新remote repository下面名字为mybranch的branch)
$git push origin HEAD:refs/for/mybranch (HEAD指向当前工作的branch,master不一定指向当前工作的branch,所以我觉得用HEAD还比master好些)
$git push origin test:master // 提交本地test分支作为远程的master分支
$git push origin :mybranch #(再origin repository里面查找mybranch,删除它。用一个空的去更新它,就相当于删除了, 但是本地还会保存的,不用担心)
- git push常见错误
1.error:failed to push some refs to …
当要push代码到git时,出现提示:
$ git push origin master
To ../remote/
! [rejected] master -> master (non-fast forward)
error: failed to push some refs to ‘../remote/’
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the ‘non-fast forward’
section of ‘git push –help’ for details.
问题(Non-fast-forward)的出现原因在于:git仓库中已经有一部分代码,所以它不允许你直接把你的代码覆盖上去。于是你有2个选择方式:
1)git push -f
强推,即利用强覆盖方式用你本地的代码替代git仓库内的内容
2) 先把git的东西fetch到你本地然后merge后再push
git fetch
git merge #这2句命令等价于
git pull
- 强制pull
$ git fetch –all
$ git reset –hard origin/master
$ git pull
- 强制push
[root@node2 www]# git push -u origin master -f
Counting objects: 81, done.
Compressing objects: 100% (66/66), done.
Writing objects: 100% (81/81), 11.94 KiB, done.
Total 81 (delta 23), reused 0 (delta 0)
remote: GitLab: You are not allowed to force push code to a protected branch on this project.
To git@cpsd.ekwing.com:liwenbin/www.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to ‘git@cpsd.ekwing.com:liwenbin/www.git’
对于private的工程不允许使用此命令强制更新,public的工程是允许强制更新的