Git版本控制:Git高级教程,git clean

http://blog.csdn.net/pipisorry/article/details/50669350

Git有很多命令行参数,使用起来非常方便。可以运行 man git log ,来看一下这些参数的作用。

本博客主要内容git大文件处理、文件比较、git blame用法、git log与git reflog、文件改动相关、cherry-pick命令、git clean

git大文件处理

git commit后,git push前查看要push的文件中是否有大文件

git diff origin/master –name-only | find -size +100M

方法1:预防,大于50M的不添加到git管理中

alias ga=’find . -size +100M ! -path *git* | cut -c 3- >> .gitignore; git add .’

或者alias ga=’git add . ; find . -size +50M ! -path *git* | xargs git reset HEAD’

Note: 还有一种就是alias ga=’find . -size -50M ! -path *git* | xargs git add’,不过这条命令如果目录下有subgit项目就会出错error。

方法2:使用lfs强行push上去

这个好像也不行,还是会push出错,并没有用!!!

安装Git LFS lets you store files up to 2 GB in size.

curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
sudo apt install git-lfs
find . -size +50M ! -path *git* | xargs git lfs track
git add .
git commit -m “update”
git push -u origin master

git lfs track设置了文件后,会提示如./song.rar already supported或者
Tracking ./JIM/train.dat
Tracking ./JIM/test_candidate.dat

会新建一个文件.gitattributes,里面内容就是大文件文件名。

quick install[Bash Scripts]

[Install v1.4.1 via PackageCloud (Linux)]

[Versioning large files]


文件比较

查看其他分支中的文件git show/git diff

直接输入 git diff 只能比较当前文件和暂存区文件差异,加参数还可以比较两次 commit 之间的差异,比较两个分支之间的差异,比较暂存区和版本库之间的差异等。

git show some-branch:some-file.js
用这个命令可以很方便地查看其他分支上的文件而无需切换到那个分支。
当然你也可以通过 git show some-branch-name:some-file-name.js 命令在终端中显示指定的文件.
你还可以将输出重定向到一个临时文件,这样你就可以再指定的编辑器中,以并排视图来查看它了。

git show some-branch-name:some-file-name.js > deleteme.js

git diff示例

查看另一个分支上文件与当前分支上文件的差异
git diff some-branch some-filename.js

查看push前与远程的区别

git diff origin/dev –name-status | grep ‘.exe’

git diff origin/master –name-only | xargs grep -size +100M 查看要push的文件中是否有大文件

git commit后,查看某个文件的修改

git diff filename

《Git版本控制:Git高级教程,git clean》

对比不同版本

git diff c0f28a2ec490236caa13dec0e8ea826583b49b7a 2e476412c34a63b213b735e5a6d90cd05b014c33

用第三方差异工具查看整个工程而非单个目录的差异git difftool -d

差异工具是Meld,在使用Linux的时候可以使用它。

假设你已经选好了比较工具,并且git能够将它作为一个合并和差异工具使用。接下来需要运行一下下面的命令,注意用你选择的差异工具的名字代替Meld:

git config –global diff.tool.meld

git config –global merge.tool meld

之后你就可以运行git difftool some-file.js 来查看文件的差异了。

但是,有些比较工具(例如meld)支持全路径比较。如果你不喜欢meld,也可以使用其他的比较工具,git difftool 支持以下的比较工具:

           kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, diffuse, opendiff, p4merge and araxis

如果你调用 git difftool 时加 -d 标志,将会对整个文件夹进行比较。有时会非常有用。

git difftool -d

《Git版本控制:Git高级教程,git clean》

使用meld比较文件差异

Meld:一个可视化的文件及目录比较工具,具有的基本功能包括:
能同时完成两个或三个文件的比较,并以图形化的方式给出各个文件的不同处;
能同时完成两个或三个目录的比较,突出显示不相同的文件、删减过的文件;
文件的合并;
文件编辑;
直接制作补丁;
可以比较本地文件与 CVS 中的文件;

$ sudo apt-get install meld

$meld /home/pika/Desktop/jquery-mouse-star-animation/index2.html /home/pika/Desktop/jquery-mouse-star-animation/index.html &

《Git版本控制:Git高级教程,git clean》

使用git diff / git difftool比较硬盘上任意两个文件的差异

$git difftool /home/pika/Desktop/jquery-mouse-star-animation/index2.html /home/pika/Desktop/jquery-mouse-star-animation/index.html

或者$git diff /home/pika/Desktop/jquery-mouse-star-animation/index2.html /home/pika/Desktop/jquery-mouse-star-animation/index.html

— a/home/pika/Desktop/jquery-mouse-star-animation/index2.html

+++ b/home/pika/Desktop/jquery-mouse-star-animation/index.html

@@ -11,8 +11,10 @@

 </style>

 </head>

 <body>

-<script type=”text/javascript” src=”js/mymouse.js” id=”mymouse”></script>

+<div style=”text-align:center;clear:both”>

+<script src=”/gg_bd_ad_720x90.js” type=”text/javascript”></script>

+<script src=”/follow.js” type=”text/javascript”></script>

+</div>

+      <iframe frameborder=”0″ scrolling=”no” src=”index2.html” width=”100%” height=”500px”></iframe>

 </body>

 </html>

\ No newline at end of file

上面输出中的—表示index.html中没有的行,+++表示index.html中多出的行(相对于index2)。

让git diff调用meld图形化差异比较工具

{让 git diff 使用 meld 的方法:默认的git diff命令比较难看,meld 是最好用的文件比较工具。}

先按上面安装meld

$mkdir ~/bin/
$vi ~/bin/git-meld.sh
#!/bin/bash
meld $2 $5
$sudo chmod +x ~/bin/git-meld.sh

配置git使用meld:
$ git config –global diff.external ~/bin/git-meld.sh

配置成功以后,在某个git管理的文件夹下,修改文件a后,再用git diff a的时候就可以直接用meld察看了。(注意这个比较只能是git管理下的文件才会调用图形界面,否则比较系统中任意两个文件时不会调用meld,所以直接用meld比较更好)

Note: 做shell的原因是GIT会送7个参数给Meld,但是Meld只需要两个参数,两个需要比较的文件名。所以不能直接用Meld。

使用git difftool (git mergetool)

git difftool 和 git mergetool是专门提供给我们以用自己的工具进行diff和merge的命令。只要配置一下就可以使用了:
git config –global diff.tool meld #配置默认的difftool
git config –global merge.tool meld #配置默认的mergetool
然后输入命令 git difftool HEAD HEAD^1 看看?
使用meld直接比较目录
虽然使用git difftool已经基本满足了我的需要,但还有个小问题:如果我要比较两次提交之间的差异时,difftool只能一个文件一个文件的比较,每次都要提 示你是否打开这个文件,然后打开meld进行比较,当你关闭meld后,才会提示下一个差异文件。这样非常浪费效率。能不能直接利用meld的目录比较能 力呢?
搜了一下,果然有人把脚本写好了: https://github.com/thenigan/git-diffall
也可以到这里下载: http://files.cnblogs.com/pengdonglin137/git-diffall-master.zip
下下来以后,进行如下配置:
git config –global diff.tool meld
git config –global alias.diffall /PATH/TO/YOUR/git-diffall
现在试试 git diffall HEAD HEAD^1 ?
多谢lxd提出遇到的问题与我分享,上述配置会遇到错误 “Expansion of alias ‘diffall’ failed; ‘/xxxx/git-diffall/git-diffall’ is not a git command”,最方便的解决方法就是创建一个软链接在你的PATH路径之一里,比如:
ln -s /PATH/TO/YOUR/git-diffall ~/bin/git-diffall
然后配置
git config –global diff.tool meld #这一行必须配置,否则diffall不知道该使用哪个diff程序
git config –global alias.diffall git-diffall

[git-diff – Show changes between commits, commit and working tree, etc]

[Linux下文件差异比较工具 ]

[10 个文件和文档的比较工具]

皮皮blog

git blame用法

出了问题后去责怪别人,是人类的天性。如果你的成品服务器出了问题,你可以非常轻松的把坏人揪出来——只需要使用git blame命令。

运行’git blame [filename]’, 你就会得到整个文件的每一行的详细修改信息:包括SHA串、作者、最后一次改动后进行的提交(commit)以及该次提交的时间戳。

Note :Git采用SHA1做为hash签名算法, 在本书中,作者为了表达方便,常常使用SHA来代指SHA1. 如果没有特别说明, 本书中的SHA就是SHA1的代称

git blame test.py

如果文件被修改了(reverted),或是编译(build)失败了; 这个命令就可以大展身手了.

你也可以用”-L”参数在命令(blame)中指定开始和结束行:

$>git blame -L 160,+10 test.py

[http://git-scm.com/docs/git-blame]

[查找问题的利器 – Git Blame]

回顾仓库历史

git log命令三个选项

  • –oneline——把每次提交间显示的信息压缩成缩减的hash值和提交信息,在一行显示。
  • –graph——该选项会在输出界面的左手边用一种基于文本的图形表示法来显示历史。
    如果你只是浏览一个单独分支的历史,那么这个功能是没有用的。
  • –all——显示全部分支的历史

以上命令综合使用的效果

《Git版本控制:Git高级教程,git clean》

快速定位故障版本git bisect

git bisect 使用分治算法查找出错版本号。

假设休假一周回来,你看了一下最新代码,发现走之前完全正常的代码现在出问题了。

你查看了一下休假之前最后一次提交的代码,功能尚且正常。不幸的是,你离开的这段时间,已经有上百次提交记录,你无法找到那一次提交导致了这个问题。

pulling-out-hair

这时你或许想找到破坏功能的bug,然后对该文件使用git blame 命令,找出并指责破坏者。

如果bug很难定位,那么或许你可以去看一下提交历史,试一下看能不能找到出问题的版本。

另一种快捷的方式则是使用git bisect,可以快速找到出问题的版本。

那么git bitsect是如何做的呢?

指定了已知的正常版本和问题版本之后,git bisectit bisect会把指定范围内的提交信息从中间一分为二,并会根据最中间的提交信息创建一个新的分支, 你可以检查这个版本是否有问题。

假设这个中间版本依然可以正常运行。你可以通过git bisect good命令告诉git。然后,你就只有剩下的一半的版本需要测试。

Git会继续分割剩下的版本,将中间版本再次到处让你测试。

Git bisect会继续用相似的方式缩小版本查找范围,直到第一个出问题的版本被找到。

因为你每次将版本分为两半,所以可以用log(n)次查找到问题版本(时间复杂度为“big O”,非常快)。

运行整个git bisect的过程中你会用到的所有命令如下:

git bisect start ——通知git你开始二分查找。

git bisect good {{some-commit-hash}} ——反馈给git 这个版本是没有问题的(例如:你休假之前的最后一个版本)。

git bisect bad {{some-commit-hash}} ——告诉git 已知的有问题的版本(例如master分支中的HEAD)。git bisect bad HEAD (HEAD 代表最新版本)。

这时git 会签出中间版本,并告诉你去测试这个版本。

git bisect bad ——通知git当前版本是问题版本。

git bisect good ——通知git当前签出的版本没有问题。

当找到第一个问题版本后,git会告诉你。这时, git bisect 结束了。

git bisect reset——返回到 git bisect进程的初始状态(例如,master分支的HEAD版本)。

git bisect log ——显示最后一次完全成功的 git bisect日志。

你也可以给git bisect提供一个脚本,自动执行这一过程。详细内容请点击:
http://git-scm.com/docs/git-bisect#_bisect_run

皮皮Blog

git log与git reflog

一个简单的git log命令,显示你最近的提交信息,以及上一次,再上一次的提交信息,以此类推。

而git reflog显示的是所有head移动的信息。记住,它是在本地的,而不是你仓库的一部分,不会包含在推送(push)和合并中(merge)。

Note: git log 如果日志过长显示不完整,则按q结束

git log

得到的提交信息是我的仓库的一部分。

《Git版本控制:Git高级教程,git clean》

命令示例:

git log –oneline –graph

git log常用参数:

  • –author=“Alex Kras” ——只显示某个用户的提交任务
  • –name-only ——只显示变更文件的名称
  • –oneline——将提交信息压缩到一行显示
  • –graph ——显示所有提交的依赖树
  • –reverse ——按照逆序显示提交记录(最先提交的在最前面)
  • –after ——显示某个日期之后发生的提交
  • –before ——显示发生某个日期之前的提交

如果这些都不好用,git还有一个 –pretty 参数,可以用来创建高级自定义输出。

例如,曾经有位主管要求在每周五提交周报。所以我每周五都运行一下这个指令: git log –author=”Alex Kras” –after=”1 week ago” –oneline,然后将输出结果编辑一下,发送给主管审核。

查看文件的详细变更git log -p
git log -p 或者 git log -p filename 不仅显示提交说明、提交者以及提交日期,还会显示这每次提交实际修改的内容。
然后你就可以使用 less 中常用的检索命令即“斜杠”后面加检索词/{{在此处添加你的检索词}}),在变更内容日志中检索指定的关键词(使用小写的n跳到下一条检索结果,大写的N跳到上一条检索结果)。

查看文件中指定位置的变更git log -L 
命令示例:git log -L 1,1:some-file.txt
你可以使用 git blame filename 追查出文件中每一行是由谁变更的。
git blame 是一个非常强大的工具,但是又是无法提供足够的信息。
git log 提供了一个 -L 的选项。这个选项允许指定文件中的某些行。Git只会输出与这些行的变更日志。这有点像带焦点的 git log -p 。

查看尚未合并的变更git log –no-merges master
如果你曾经与很多小伙伴工作在同一个持久分支上,也许会有这样的经历,父分支(例如:master)上的大量合并同步到你当前的分支。这使得我们很难分辨哪些变更时发生在主分支,哪些变更发生在当前分支,尚未合并到master分支。
git log –no-merges master..可以解决这个问题。注意–no-merges 标志意味着只显示没有合并到任何分支的变更,master..选项,意思是指显示没有合并到master分支的变更(在master后面必须有..)。
你也可以运行 git show –no-merges master.. 或者 git log -p –no-merges master.. 命令(输出结果相同)来查看一下尚未合并的文件变更。

git relog

你提交了一个你不想要提交的代码,最后你通过使用硬重置(hard reset)使其回到了之前的状态。稍后,你意识到,在这个过程中你丢失了一些其他的信息,并想要退回或是至少能看一眼。git reflog命令可以帮你做到这一点。

git reflog显示了一个提交信息(b1b0ee9 – HEAD@{4}),这是我使用硬重置(hard reset)时丢失的那个。

《Git版本控制:Git高级教程,git clean》

皮皮Blog

暂存一个文件的部分改动git add -p

通常来讲,创建一个基于特性的提交是一个良好的做法,就是说,每次提交都必须代表一个新特性的产生或者是一个bug的修复。考虑一下,如果你修复了两个bug,或是添加了多个新特性但是却没有提交这些变化会怎样呢?在这种情况下,你可以把这些变化放在一次提交中。但是还有一个更好的方法:把文件分别暂存(Stage)然后分别提交。

比如说,你对一个文件进行了多次修改并且想把他们分别提交。这种情况下,你可以在添加命令(add)中加上-p选项

git add -p [file_name]

让我们演示一下。我在file_name文件中添加了3行文字,而且我只想提交第一行和第三行。我们先看一下git diff显示的结果。

《Git版本控制:Git高级教程,git clean》

然后,我们看一下,在添加命令(add)中加上-p选项后会发生什么。

《Git版本控制:Git高级教程,git clean》

看上去,Git假定所有的改变都是针对同一件事情的,因此它把这些都放在了一个块里。你有如下几个选项:

输入y来缓存该块

输入n不缓存该块

输入e来人工编辑该块

输入d来退出或进入下一个文件

输入s来分割这个块

对我们而言,我们肯定希望把它分成几个部分,有选择的添加一部分而忽略其他的。

《Git版本控制:Git高级教程,git clean》

正如你所看到的,我们添加了第一行和第三行而忽略了第二行。你可以在之后查看仓库状态并进行提交。

《Git版本控制:Git高级教程,git clean》

合并多次提交git rebase

当你提交你的代码进行审核并创建一个pull request时(在开源项目中常常发生这样的情况),你经常会在代码被采纳前,要求修改一些代码。你进行了一些修改,而在下一次审核中,又会被要求进行另外的修改。你不知道还有多少次修改等着你,在你知道以前,你进行了多次额外的提交。理想的状态是,你可以使用rebase命令,把他们都合并成一次提交。

git rebase -i HEAD~[number_of_commits]

如果你希望合并最后两次提交,您需要以下命令

git rebase -i HEAD~2

使用该命令,你会进入一个交互式的界面,显示了最后两次提交,并且询问你要压缩哪些。理想状态是你pick最近的一次提交并把它和之前的提交squash。

《Git版本控制:Git高级教程,git clean》

接下来你会被要求为合并后的这次提交填写描述信息。这一个过程实际上重写了你的提交历史。

《Git版本控制:Git高级教程,git clean》

保存尚未提交的改动git stash

比方说你正在解决一个bug或是添加某个新功能,这时你突然被要求展示你的工作。你当前的工作还没有完成到进行提交的地步,而且你在这个阶段也没办法展示你的工作(如果不回退所有变化的话)。在这种情况下,git stash可以拯救你。stash命令本质上是保存了你全部的改动以供将来使用。保存你的改动,你只需要运行如下命令:

git stash

查看暂存列表,你可以运行如下命令:

git stash list

《Git版本控制:Git高级教程,git clean》
如果你不想保存了或是想要恢复这些改动,你使用如下命令:
git stash apply
在最后一张截图中,你可以看到,每一次保存都有一个标示符,一个独一无二的数字(尽管我们此处只有一次保存),万一你只想使用某些保存,你需要在apply命令后指明标示符。
git stash apply stash@{2}
《Git版本控制:Git高级教程,git clean》

[关于git pull的问题,如何在不commit的前提下pull回来?]

检查丢失的提交git fsck

尽管reflog是一种查看丢失提交的方法,但是它在大型仓库中行不通。这时就该fsck

(file system check)出场了。

git fsck –lost-found

《Git版本控制:Git高级教程,git clean》
这里你可以看到丢失的提交,你可以使用git show [commit_hash]来查看这些提交所包含的改动或者是使用git merge [commit_hash]来恢复它。
git fsck比reglog有一个优势。比如你删除了一个远端分支并且克隆了仓库,使用fsck命令你可以搜索并恢复该远端分支。

变更基线的几点说明

示例:git pull –rebase

之前我们说过在远程分支上工作会有大量的合并提交。使用 git rebase 可以避免这些提交。

总的来说我认为变更基线是高级特征,最好是留到另一篇文章中详细介绍。

甚至在git book中也有这样的论述:

但是,令人狂喜的变更基线并不是任何情况下都适用,一言以蔽之:

若是工作区中存在尚未提交到仓库的变更,请不要使用变更基线。

如果遵照这条指南,不会有什么问题。不然,你可能会招致厌恶与谩骂。

https://git-scm.com/book/en/v2/Git-Branching-Rebasing#The-Perils-of-Rebasing

也就是说,变更基线本身并不可怕,关键在于使用方式。

或许,最好的方法是使用交互式变更基线,调用命令为 git rebase -i {{某个提交序列号}}。运行这条命令,会打开一个带有自解释指令的编辑器。由于变更基线不在本文的叙述范围之内,我们就此而止,不再深究。

《Git版本控制:Git高级教程,git clean》

变更基线一个非常有用的特殊用法 git pull –rebase。

举个例子,假设你正在master分支的一个本地版本上工作,你已经向仓库提交了一小部分变更。与此同时,也有人向master分支提交了他一周的工作成果。当你尝试推送本地变更时,git提示你需要先运行一下 git pull , 来解决冲突。作为一个称职的工程师,你运行了一下 git pull ,并且git自动生成了如下的提交信息。

Merge remote-tracking branch ‘origin/master’

尽管这不是什么大问题,也完全安全,但是不太有利于历史记录的聚合。

这种情况下,git pull –rebase 是一个不错的选择。

这个命令会迫使git将远程分支上的变更同步到本地,然后将尚未推送的提交重新应用到这个最新版本,就好象它们刚刚发生一样。这样就可以避免合并以及随之而来的丑陋的合并信息了。

修复而非新建提交git commit –amend

假设提交之后,你意识到自己犯了一个拼写错误。你可以重新提交一次,并附上描述你的错误的提交信息。但是,还有一个更好的方法:
如果提交尚未推送到远程分支,那么按照下面步骤简单操作一下就可以了:
修复你的拼写错误
将修正过的文件暂存,通过git add some-fixed-file.js
运行 git commit –amend 命令,将会把最近一次的变更追加到你最新的提交。同时也会给你一个编辑提交信息的机会。
准备好之后,将干净的分支推送到远程分支。

《Git版本控制:Git高级教程,git clean》
如果你工作在自己的分支,甚至可以在已经推送之后修正提交,你需要使用 git push -f (-f 代表强制执行),这条指令可以重写历史。但是,不要试图在一个很多人共同工作的分支(正如我们在变更基线那一部分讨论的分支)上这样做。此时,新建一次提交,在提交信息中描述错误,应该是最好的补救措施。

撤销而不产生提交信息git revert -n

如果打算撤销之前一次或者两次的提交,查看这些提交都做了哪些变更,哪些变更又有可能引发问题,这个命令非常方便。
通常,git revert 会自动将回退的文件提交到仓库,需要你写一个新的提交信息。-n 标志告诉git先别急着提交,因为我只是想看一眼罢了。

皮皮Blog

cherry-pick命令

它的名字就意味着它的功能!简而言之,cherry-pick是指从不同的分支里选择某次提交并且把它合并到当前的分支来。如果你在并行的开发某两个或多个分支,你可能会注意到有一个bug存在于所有的分支中。如果你在一个分支中解决了它,你可以使用cherry-pick来把这次提交合并进其他的分支而不会搞乱其他的文件或是提交。

让我们想象一个可以使用该命令的场景。我有两个分支,并且我想要把b20fd14: Cleaned junk这次提交使用cherry-pick的方法放入到另一个分支。

《Git版本控制:Git高级教程,git clean》

我切换到我想要放入该提交的分支,然后运行如下命令:

git cherry-pick [commit_hash]

《Git版本控制:Git高级教程,git clean》

尽管我们本次使用cherry-pick没什么问题,但是你应该清楚这个命令会带来冲突,请谨慎使用。

皮皮Blog


git clean

删除 一些 没有 git add 的 文件(也就是untracked file)

git clean 参数

    -n 显示 将要 删除的 文件 和  目录

     -f 删除 文件,-df 删除 文件 和 目录

[git clean]

from:http://blog.csdn.net/pipisorry/article/details/50669350

ref:让你的Git水平更上一层楼的10个小贴士

日常使用 Git 的 19 个建议

点赞