git(2)

目录

 

远程仓库

远程分支VS远程跟踪分支VS本地分支

跟踪分支

推送本地分支

拉取或抓取

删除远程分支

git服务器安全地管理代码

reset和checkout可以胜任撤销工作

“三棵树”

例程

总结

你的打赏是我奋笔疾书的动力!


远程仓库

查看所有的远程仓库:git remote -v

$ git remote -v
bakkdoor  https://github.com/bakkdoor/grit (fetch)
bakkdoor  https://github.com/bakkdoor/grit (push)
cho45     https://github.com/cho45/grit (fetch)
cho45     https://github.com/cho45/grit (push)
defunkt   https://github.com/defunkt/grit (fetch)
defunkt   https://github.com/defunkt/grit (push)
koke      git://github.com/koke/grit.git (fetch)
koke      git://github.com/koke/grit.git (push)
origin    git@github.com:mojombo/grit.git (fetch)
origin    git@github.com:mojombo/grit.git (push)

查看远程仓库某个远程仓库的详细信息:git remote show [remote-name]

$ git remote show origin
* remote origin
  URL: https://github.com/my-org/complex-project
  Fetch URL: https://github.com/my-org/complex-project
  Push  URL: https://github.com/my-org/complex-project
  HEAD branch: master
  Remote branches:
    master                           tracked
    dev-branch                       tracked
    markdown-strip                   tracked
    issue-43                         new (next fetch will store in remotes/origin)
    issue-45                         new (next fetch will store in remotes/origin)
    refs/remotes/origin/issue-11     stale (use 'git remote prune' to remove)
  Local branches configured for 'git pull':
    dev-branch merges with remote dev-branch
    master     merges with remote master
  Local refs configured for 'git push':
    dev-branch                     pushes to dev-branch                     (up to date)
    markdown-strip                 pushes to markdown-strip                 (up to date)
    master                         pushes to master                         (up to date)
    这个命令列出了当你在特定的分支上执行 git push 会自动地推送到哪一个远程分支。 它也同样地列出了哪些远程分支
不在你的本地,哪些远程分支已经从服务器上移除了,还有当你执行 git pull 时哪些分支会自动合并。

添加远程仓库:git remote add <shortname> <url>

$ git fetch pb
remote: Counting objects: 43, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 43 (delta 10), reused 31 (delta 5)
Unpacking objects: 100% (43/43), done.
From https://github.com/paulboone/ticgit
 * [new branch]      master     -> pb/master
 * [new branch]      ticgit     -> pb/ticgit

 从远程仓库中获得数据:git fetch [remote-name]命令会将数据拉取到你的本地仓库 - 它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。git clone会自动将其添加为远程仓库并默认以 “origin” 为简写。

git pull命令来自动的抓取然后合并远程分支到当前分支,如果你有一个分支设置为跟踪一个远程分支的话。

推送到远程仓库:git push [remote-name] [branch-name]将 本地仓库的master 分支推送到 origin 服务器的master 分支[git push省略2个方括号的默认行为],当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。

远程仓库paul的移除:git remote rm  paul 本地不在需要远程仓库了。

远程仓库的重命名:git remote rename pb paul

远程分支VS远程跟踪分支VS本地分支

远程跟踪分支(已经clone或者拉取到本地的远程分支)是远程分支(该分支在服务器上)状态的引用。 它们是你不能移动的本地引用,当你做任何网络通信操作时,它们会自动移动。 远程跟踪分支像是你上次连接到远程仓库时,那些远程分支所处状态的一个直接引用。它们以 (remote)/(branch) 形式命名,例如:origin/master。

git clone会为你自动将这个远程仓库(用一个url指代)命名为 origin,拉取它所有数据(包括所有的分支的数据,还有tag等等)到本地仓库,创建一个指向它的 master 分支的指针,并且自动地将其命名为 origin/master(远程跟踪分支的引用)---叫做origin/master 分支, Git 也会给你一个与 origin/master指向同一个地方的指针master---叫做本地master 分支 ,这样你就有工作的基础。

本地分支也叫“跟踪分支”(例如:master ),跟踪的是远程跟踪分支,远程跟踪分支也叫“上游分支”(例如:origin/master ),而它又跟踪远程分支(例如:远程仓库的master分支 )。

跟踪分支

刚刚拉取下来的远程跟踪分支还没有本地分支跟踪它,所以你使用git branch -v命令只会看到本地master分支跟踪了远程跟踪分支origin/master,你可以使用git checkout -b [branch] [remotename]/[branch]基于[remotename]/[branch]来创建一个本地分支[branch]来跟踪远程跟踪分支[remotename]/[branch],或者使用git checkout --track [remotename]/[branch]来创建一个本地分支[branch]来跟踪远程跟踪分支[remotename]/[branch],如果想要将本地分支与远程分支设置为不同名字,你只能用第一种方式。

推送本地分支

你创了一个新分支想要和其他协作者共享,你需要 就是推送你的新分支。git push (remote) (branch) 或者 git push (remote) refs/heads/branch:refs/heads/branch 或者 git push (remote) (branch):(branch)

git push origin serverfix:awesomebranch:推送本地分支serverfix到一个命名不相同的远程分支awesomebranch。

拉取或抓取

git fetch:从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容,它只会获取数据然后让你自己合并。 尤其当抓取到新的远程跟踪分支时,本地不会自动生成一个指向相同的本地分支,需要自己生成本地分支来跟踪远程跟踪分支。git fetch默认是从origin仓库抓取数据。

git merge :紧跟着git fetch之后,来合并远程跟踪分支到当前的本地分支。例如:git merge origin/master。

删除远程分支

假设你你和你的协作者已经完成了一个特性分支的任务并且将特性分支合并到了远程仓库的 master 分支(或任何其他稳定代码分支)。这时候你需要删除远程仓库的特性分支:

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

基本上这个命令做的只是从服务器上移除这个指针,不会真的删除,是可以恢复的。

git服务器安全地管理代码

为了在版本控制系统里设置一套完善的权限控制,例如:每个人是否有读写权限会精确到每个分支甚至每个目录下,Gitolite就是放在服务器端做权限控制的工具,它基于Git的钩子(hook)。

当然具有权限管理功能的软件系统不止Gitolite一种,提供网页入口的GitLab也是具有自己的权限管理,代码管理者通过网页端可以管理代码和权限,开发者通过网页端查看代码等等。

除过可以私自部署以上两种系统外,还可以使用网络上的第三方代码托管方式,例如国外的github和国内的码云,他们提供免费的不带权限管理的公共项目的托管方式,也提供私有项目的托管方式,当然了,这是付费的。

reset和checkout可以胜任撤销工作

“三棵树”

撤销刚刚提交的(部分或所有)文件到祖辈的某一次提交的版本上?撤销刚刚提交的(部分或所有)文件到祖辈的某一次提交的版本上,并且让索引区的(部分或所有)文件也撤销到这个版本上?撤销刚刚提交的(部分或所有)文件到祖辈的某一次提交的版本上,不仅让索引区的(部分或所有)文件也撤销到这个版本上,工作区的(部分或所有)文件也被撤销到这个版本上?

工作区、索引区(暂存区)、版本这些概念其实足够让你看的不开心。学习到这里,其实你才开始真正接触git的实质,没错,git这个系统维护了“三棵树”。git add会把工作区的“树”添加到索引区,git commit会把索引区的“树”提交到本地仓库的某一分支上,并用head指针指向该分支的最后一次提交的“树”。工作区所谓的“树”是指所有的目录和这些目录中的文件,在工作区我们可以直观地看到这棵“树”,但是在索引区和某分支上提交的“树”有一些不同,这棵“树”的信息存储在本地仓库中,例如下面就图示了某次提交到仓库的一棵“树”:

é¦æ¬¡æ交对象åå¶æ ç»æã

看到了吗?这棵树用tree对象来表示,且有一个省略的hash代号92ec2, 其中包括这棵树的目录信息(所有子目录的校验和,具体怎么回事去查详细解释),这棵树所属的文件使用blob对象来表示,blob对象的代号是对应的文件二进制数据(估计是utf-8)的has1值,它唯一指代了这个文件的某一个版本,只要对这个文件修改了,那么就会有另一个唯一的has1值代号,也就是会产生另一个blob对象,也就是只要修改了该文件,那么该文件会被记录成另一个版本。并且图示中有五个对象:三个 blob 对象(保存着文件快照(副本))、一个树对象(记录着目录结构和 blob 对象索引)以及一个对应的提交对象(包含着指向前述树对象的指针和所有提交信息)。

所以工作区中是“直观的树”,它和索引区以及某分支上提交的“树”有所不同,reset和checkout命令被用来操作这三棵树

例程

下面是一个例子,假设我们有一个根目录和根目录下的仅有的一个文件file.txt,并且该文件有三次提交,如下图(head指针指向最后一次提交的那棵树):

reset start

命令一:git reset --soft HEAD~ ,其中HEAD~ 是指代HEAD的父节点(父树,也即是9e5e6a4,在命令中可换成这个hash省略代号),HEAD~2指代当前HEAD指针指向的树的爷爷树,HEAD~n依次指代。该命令的操作效果如下:只是让HEAD指向的分支指针(master)移动到了HEAD的父树(或者某个hash指代的树)上。

reset soft

命令二:git reset [--mixed] HEAD~,其实比git reset --soft HEAD~多进一步,让索引区的树也指向HEAD的父树(或者某个hash指代的树)上。

reset mixed

命令三: git reset --hard HEAD~又比git reset [--mixed] HEAD~多进一步,让工作区的树也重置成(恢复成、撤销成)HEAD的父树(或者某个hash指代的树)。

reset hard

 --hard 标记是 reset 命令唯一的危险用法,若工作区的文件修改了还未提交,该命令仍会覆盖它从而导致无法恢复。

有时候我们只想撤销某个文件,或者某几个文件,而且这种撤销只能撤销索引区的数据,即是:git reset [--mixed] HEAD file.txt,我们通常简写为:git reset  file.txt,它会略过第一步操作:让HEAD指向的分支指针(master)移动。只有仅有的一步操作:让索引区的file.txt文件撤销成HEAD指向的那一版。且没有--soft和--hard标记的命令。

回过头来看看第一篇中的撤销操作用例---git reset HEAD <file>... 取消暂存区域文件的命令的完整形式应该是:git reset [--mixed] HEAD <file>,它和git add是一对相向的操作。

checkout和reset的一个重要区别是:reset移动的是HEAD指向的分支指针,而checkout移动的是HEAD指针本身。例如:git checkout [branch] 与运行 git reset --hard [branch]和类似,都会把三棵树撤销成branch指向的树,但是有重要的一点是:checkout移动的是HEAD指针本身,reset移动的是HEAD指向的分支指针。如下图:

reset checkout

总结

下面的速查表列出了命令对三棵树的影响。HEAD” 一列中的 “REF” 表示该命令移动了 HEAD 指向的分支指针,而`‘HEAD’' 则表示只移动了 HEAD 指针本身。 特别注意 WD Safe? 一列 - 如果它标记为 NO,那么运行该命令之前请考虑一下,它有危险。

 HEADIndexWorkdirWD Safe?

Commit Level

    

reset --soft [commit]

REF

NO

NO

YES

reset [commit]

REF

YES

NO

YES

reset --hard [commit]

REF

YES

YES

NO

checkout [commit]

撤销三棵树为某一次提交的树,但是只移动HEAD指针指向某一次提交的树,该分支的指针还指着最后一次提交树,并且工作区原来修改了的数据被安全地和某一次提交的树进行了简单的合并,并没有被丢弃。

HEAD

YES

YES

YES

File Level

    

reset (commit) [file]

撤销暂存区的文件file为某一次提交的树下的那个版本的文件,HEAD 指向的分支指针和HEAD 指针不会移动,并且工作区已被修改的数据是安全的,不会被丢弃。

NO

YES

NO

YES

checkout (commit) [file]

撤销暂存区和工作区的文件file为某一次提交的树下的那个版本的文件,HEAD 指向的分支指针和HEAD 指针不会移动,并且工作区已被修改的数据不安全,会被丢弃。

NO

YES

YES

NO

你的打赏是我奋笔疾书的动力!

支付宝打赏:

微信打赏:

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值