git学习

Posted 做枚温婉的妹纸吧哈哈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了git学习相关的知识,希望对你有一定的参考价值。

文件状态

tracked和untracked,后者属于在版本库中没有快照的,当运行git add 后文件放到了暂存区,变成tracked状态,当commit 后,文件此刻的版本会在版本库中形成记录。

git diff

git diff:用于查看工作区和暂存区间的差异
git diff --cachedgit diff --staged 用于查看暂存区中的内容。
git diff HEAD 显示工作区和上次提交之间的差异。

git commit -a -m 'added new benchmarks'

-a 表示跳过add 这一步骤,直接将已跟踪过的文件的修改进行提交,跳过了暂存这个步骤。

git rm --cached <filename>

删除git追踪文件,但不删除文件本身(可能从暂存区撤回到工作区)。

git commit --amend

修改提交消息或者将忘记提交的文件合并到上次的提交中。

git reset HEAD <filename>

取消暂存区的内容,放回工作区。

git checkout -- <filename>

丢弃工作区的修改。

git remote add <shortname> <url>

添加远程仓库,使用git remote 可查看已关联的远程仓库。 origin 是默认的所克隆的远程仓库的名字.

git show

显示最近一次提交与之前相比的差别快照。给出参数还可以有更多的显示方式。例如git show HEAD@5 表示查看上5次提交。

分支说明

git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或不管是什么名字的默认分支)。 运行 git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。
克隆之后创建一个指向origin的 master 分支的指针,并且在本地将其命名为 origin/master( 远程分支以该形式引用:<remote>/<branch>)。 Git 也会给你一个与 origin 的 master 分支在指向同一个地方的本地 master 分支,这样你就有工作的基础。在git fetch/git pull后origin/master会移动。

  • 分支其实就是指向最后一次的提交对象的指针,是指向提交对象的可变指针。而提交对象包含了指向上一次提交对象(父对象)的引用(形成了链表,方便回到别的版本)、树对象(保存了目录结构、指向blob对象的引用,而blob对象存储了文件的快照,快照在stage的时候生成?)的引用,提交的作者、邮箱等信息。
    结构如:
分支(master\\dev...是指针)--> commit obj-->tree obj --> blob obj
  • 创建分支就是生成了一个新的可移动的指针,指向当前的commit obj。
    HEAD 指向了当前的分支。切换分支就是将HEAD 指向一个新的对象。

如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。

最好的方法是,在你切换分支之前,保持好一个干净的状态(没有未提交的内容)

当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”

案例:分支创建与合并

文件冲突

当两个分支对同一个文件的同一部分进行了修改,就会造成冲突。
比如master上对文件某处做了修改,然后你在dev分支上的同一处也做了修改,之后你在dev上git merge master ,如果文件还没有addcommit,会让你先将文件进行提交后才能合并,提交后就会差生冲突:

<<<<<<< HEAD
  // someting in dev
=======
>>>>>>> master
  // something in master

即便你在合并之前将文件进行了stash,合并完了后再stash pop ,也会形成冲突,不过看起来是这样的:

<<<<<<< Updated upstream
   // something in master
=======
>>>>>>> Stashed changes
   // something in dev

防止冲突的办法是:如果有可能对文件的同一处进行操作,那么在完成合并之后再对文件进行修改。

在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。

跟踪新的远程分支:

git remote add newRemote url

git fetch newRemote //此时本地并没有远程的文件,只会在本地生成newRemote/remoteBranch指针指向远程的remoteBranch分支

git merge newRemote/remoteBranch //将远程的remoteBranch分支合并到本地的当前分支

//也可以在远程分支的基础上创建另一个分支
git checkout -b newLocalBranch newRemote/remoteBranch

直接从远程分支上检出的本地分支叫跟踪分支,运行git pull 会直接拉取所跟踪的远程分支内容并自动完成合并。例如本地的master是远程origin/master的跟踪分支,上面的newLocalBranch是newRemote/remoteBranch的跟踪分支。

git push [remote-name] [branch-name]

如果本地分支和远程分支名字不同,可以这样做: git push origin localbranch:remotebranch

删除远程分支

git push origin --delete serverfix

参考文档:Git 分支 - 远程分支

变基

这是相对于三方合并来说的另一种合并方式。三方合并是并行的,提交历史有分叉,而变基使得并行的开发看起来是串行的,合并完成后查看历史没有分叉,使得提交历史更整洁。
例如从master的c1节点开始检出到dev分支,并开发到c3(c1-c3),然后在master上从c1节点开始开发到c2,之后在master上进行合并:

c1<--c3<--
  <--c2<--c4

到c4节点,是对c1、c2、c3进行了简单的三方合并,此时dev分支指针仍指向c3。
而变基是将c3的修改完全按需复制到c2上,然后dev和master的指针都指向了c4:

c1<--c2<--c3<--c4

操作步骤是:

//dev分支
git rebase master  //打补丁到master上
git checkout master
git merge dev //master,dev指向同一个提交节点

表示当前提交的父提交。

也可以在 ^ 后面添加一个数字——例如 d921970^2 代表 “d921970 的第二父提交” 这个语法只适用于合并(merge)的提交,因为合并提交会有多个父提交。 第一父提交是你合并时所在分支,而第二父提交是你所合并的分支

HEAD~

与上面的命令一个意思,不同的是后面加了数字的情况, HEAD~2表示第一父提交的父提价

git log master..dev

双点语法用于查看在dev中而没有合并到master分支上的提交。
git log origin/master..HEAD 为在当前分支中而不在远程分支中的提交。

以上是关于git学习的主要内容,如果未能解决你的问题,请参考以下文章

Git学习Git如何Clone带有Submodule的仓库?

Git如何检出指定目录或文件

git 检出项目部分目录(稀疏检出)

如何解决git中的分歧?

Git检出指定目录实践

Git:将子模块文件检出到单个目录中