git笔记

实际上 git status的显示比较简单,仅仅是列出了修改过的文件,如果要查看具体修改了什么地方,可以用git diff命令。稍后我们会详细介绍git diff,不过现在,它已经能回答我们的两个问题了:当前做的哪些更新还没有暂存?有哪些更新已经暂存起来准备好了下次提交?git diff会使用文件补丁的格式显示具体添加和删除的行。


要查看尚未暂存的文件更新了哪些部分,不加参数直接输入git diff


此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。

若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用git diff --cached命令。(Git 1.6.1及更高版本还允许使用git diff --staged,效果是相同的,但更好记些。)

请注意,单单 git diff不过是显示还没有暂存起来的改动,而不是这次工作和上次提交之间的差异。所以有时候你一下子暂存了所有更新过的文件后,运行git diff后却什么也没有,就是这个原因。

移除文件

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。可以用git rm命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。

如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项-f(译注:即 force的首字母),以防误删除文件后丢失修改的内容。

另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆.a编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在.gitignore文件中补上,用--cached选项即可:

$ git rm --cached readme.txt

后面可以列出文件或者目录的名字,也可以使用 glob模式。比方说:

$ git rm log/\*.log

注意到星号 *之前的反斜杠\,因为 Git有它自己的文件模式扩展匹配方式,所以我们不用 shell来帮忙展开(译注:实际上不加反斜杠也可以运行,只不过按照 shell扩展的话,仅仅删除指定目录下的文件而不会递归匹配。上面的例子本来就指定了目录,所以效果等同,但下面的例子就会用递归方式匹配,所以必须加反斜杠。)。此命令删除所有log/目录下扩展名为.log的文件。类似的比如:

$ git rm \*~

会递归删除当前目录及其子目录中所有 ~结尾的文件。

移动文件

不像其他的 VCS 系统,Git并不跟踪文件移动操作。如果在 Git中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次改名操作。不过 Git非常聪明,它会推断出究竟发生了什么,至于具体是如何做到的,我们稍后再谈。

既然如此,当你看到 Git mv命令时一定会困惑不已。要在 Git中对文件改名,可以这么做:

$ git mv file_from file_to

它会恰如预期般正常工作。实际上,即便此时查看状态信息,也会明白无误地看到关于重命名操作的说明:

$ git mv README.txt README

$ git status

On branch master

Changes to be committed:

  (use "git reset HEAD <file>..." to unstage)


        renamed:    README.txt -> README

其实,运行 git mv就相当于运行了下面三条命令:

$ mv README.txt README

$ git rm README.txt

$ git add README


git log 有许多选项可以帮助你搜寻感兴趣的提交,接下来我们介绍些最常用的。

我们常用 -p选项展开显示每次提交的内容差异,用-2则仅显示最近的两次更新:


该选项除了显示基本信息之外,还在附带了每次 commit的变化。当进行代码审查,或者快速浏览某个搭档提交的 commit的变化的时候,这个参数就非常有用了。

某些时候,单词层面的对比,比行层面的对比,更加容易观察。Git提供了--word-diff选项。我们可以将其添加到git log -p命令的后面,从而获取单词层面上的对比。在程序代码中进行单词层面的对比常常是没什么用的。不过当你需要在书籍、论文这种很大的文本文件上进行对比的时候,这个功能就显出用武之地了。

修改最后一次提交

有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操作,可以使用--amend选项重新提交:

$ git commit --amend

此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,但将要提交的文件快照和之前的一样。

启动文本编辑器后,会看到上次提交时的说明,编辑它确认没问题后保存退出,就会使用新的提交说明覆盖刚才失误的提交。

如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行--amend提交:

$ git commit -m 'initial commit'

$ git add forgotten_file

$ git commit --amend

上面的三条命令最终只是产生一个提交,第二个提交命令修正了第一个的提交内容。

取消已经暂存的文件

接下来的两个小节将演示如何取消暂存区域中的文件,以及如何取消工作目录中已修改的文件。不用担心,查看文件状态的时候就提示了该如何撤消,所以不需要死记硬背。来看下面的例子,有两个修改过的文件,我们想要分开提交,但不小心用git add .全加到了暂存区域。该如何撤消暂存其中的一个文件呢?其实,git status的命令输出已经告诉了我们该怎么做:

$ git add .

$ git status

On branch master

Changes to be committed:

  (use "git reset HEAD <file>..." to unstage)


        modified:   README.txt

        modified:   benchmarks.rb

就在 “Changes to be committed”下面,括号中有提示,可以使用git reset HEAD <file>...的方式取消暂存。好吧,我们来试试取消暂存 benchmarks.rb文件:

upstream不是针对远程仓库的,而是针对branch的,这一点应了那位童鞋所说的第二句话。但是upstream和有几个远程库没有必然联系。比如远程库A上有3个分支branch1、branch2、branch3。远程库B上有3个分支branchx、branchy、branchz。本地仓库有2个分支local1和local2。那么当初始状态时,local1和local2和任何一个分支都没有关联,也就是没有upstream。当通过git branch --set-upstream-to A/branch1 local1命令执行后,会给local1和branch1两个分支建立关联,也就是说local1的upstream指向的是branch1。这样的好处就是在local1分支上执行git push(git pull同理)操作时不用附加其它参数,Git就会自动将local1分支上的内容push到branch1上去。同样,local2分支也可以和远程库A和远程库B上的任何一个分支建立关联,只要给local2分支设置了upstream,就可以在local2分支上用git push(git pull同理)方便地与目标分支推拉数据。
综上所述,upstream与有几个远程库没有关系,它是分支与分支之间的流通道。
再来说说git push -u和git branch --set-upstream-to指令之间的区别。
举个例子:我要把本地分支master与远程仓库origin里的分支gaga建立关联。
(如果使用下列途径1的话,首先,你要切换到master分支上(git checkout master))
两个途径:1. git push -u origin gaga 2. git branch --set-upstream-to=origin/gaga master
这两种方式都可以达到目的。但是1方法更通用,因为你的远程库有可能并没有gaga分支,这种情况下你用2方法就不可行,连目标分支都不存在,怎么进行关联呢?所以可以总结一下:git push -u origin gaga 相当于 git push origin gaga + git branch --set-upstream-to=origin/gaga master


作者:王轩
链接:http://www.zhihu.com/question/20019419/answer/48434769
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001374831943254ee90db11b13d4ba9a73b9047f4fb968d000

1.场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

2.场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。


3.场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id

  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

4.

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

$ git checkout -- test.txt

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容


还记得我们之前推送master分支到远程origin吗?

git push -u origin master

推送dev也是一样的,只要指定分支名为dev就可以了,

git push -u origin dev 

  • 同学A开头写了个项目,老板让我也跟着做,同学A说,你到github上图clone我的代码吧

git clone git@github.com:....

这是,你用git branch看看,这只是clone了master分支,dev呢?这可是费劲苦心,要在同学A的dev分支上开发,就必须创建远程的dev分支到本地

git checkout -b dev origin/dev 

再用git branch看看?有了吧。

  • 在同学A的基础上我又添了新功能,老板催着,赶紧提交

git checkout dev 

git pull origin dev 

  • 老板某天突然和我说:你看同学A,又修改了好多Bug,还不下下来学学

git pull origin dev  

可能出现冲突,解决后才能进行下一次的提交。

极少的场合,要不就是老板的老婆月经乱了,要不就是。。。哎,不说了,非要删除远程dev分支,也是有办法的,

git push oringin :dev 


git add的作用就是创建一个blob文件来记录最新的修改代码,并在index file里添加一个 到此blob的链接

git commit会将index file中的改变写到git仓库;

commit -a会将“当前工作目录”的改动同时写到“index file”和“git仓库”

git diff总会拿git仓库来作为比较对象之一;日过git diff的参数是HEAD,则另一个比较对象就确定为“当前工作目录”;如果参数是--cached,则另一个比较对象就被确定为“index file”。


git reset 

仅用HEAD指向的目录树充值暂存区,工作区不受影响。相当于把git add命令更新到暂存区的内容撤出暂存区。

git reset -- filename 用版本库中HEAD版本中的filename文件填充暂存区中的filename,即将文件filename的改动撤出暂存区,暂存区中的其他文件不变。相当于命令git add filename的逆操作。执行结束后暂存区中的filename和HEAD版本中的filename保持一致。

git reset --soft HEAD^

工作区和暂存区不变,将版本库变为第二新的版本,即HEAD的前一个版本。用于对最新的提交或说明不满意时,撤销最新提交以便重新提交。

git reset HEAD^

工作区不变,把暂存区和版本库回退到HEAD的前一个版本。

git reset --hard HEAD^

把版本库、暂存区和工作区都回退到HEAD的前一个版本。head版本的提交全部丢失。慎用!

使用参数--mixed或者不使用参数(默认为--mixed

    HEAD 最近一个提交

    HEAD^ 上一次提交

    HEAD^ ^ 上一次的 上一次的提交(倒数第三次)

    HEAD^^^ 倒数 第四次的 提交

----------------------

    HEAD~0 最近一个提交

    HEAD~1 上一次提交

    HEAD^2 上一次的 上一次的提交(倒数第三次)

    HEAD^3 倒数 第四次的 提交

git revert 会产生一个新的 commit,它和指定 SHA 对应的 commit 是相反的(或者说是反转的)。如果原先的 commit 是“物质”,新的 commit 就是“反物质” — 任何从原先的 commit 里删除的内容会在新的 commit 里被加回去,任何在原先的 commit 里加入的内容会在新的 commit  里被删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值