1、添加未跟踪文件为跟踪文件
2、把跟踪文件的在工作区中的改动加入暂存区
3、在解决冲突的时候把冲突文件解决后通过git add 命令将其标记为以解决
??表示是新文件,新建后未加入版本库的文件
A 标记表示新添加到暂存区中的文件
M表示修改过的文件
左边的M表示修改过并添加到了暂存区
右边的M表示被修改过但是没有放入暂存区
MM表示有一部分修改了并添加到了暂存区后有修改了一部分切没有添加到暂存区
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
--staged
git diff 比较在当前分支中当前分支上,工作区和上一次暂存区快照的差异
git diff commitId 比较的是当前分支的工作区的内容和commitId提交点的差异(即修改还没有被提交到和commitId处的代码差异)
git diff 9bdf372 53b68ea 表示9bdf372相对于53b68ea的改变 如果把commitID替换则会看到完全相反的结果
必须注意 git fetch 命令会将数据拉取到你的本地仓库 -它并不会自动合并或修改你当前的工作。
git fetch 一定不会产生冲突,它值修改本地仓库而且是从本地仓库的远程分支处接上把服务器上提交的补丁拉下来
如果本地的分支和服务器上的分支不在一起,即本地分支先与服务器分支时,如下本地master比远程master多一个提交
* 6f76c80 (HEAD -> master) 1111
| * 4abed5e (origin/test) create test file
|/
* 691f18a (origin/master) clone1
* 7b15b7a conflict by clone 1
* cb54dc8 clone1 1111x
当远程master有修改后,在本地的master上使用git fetch后得到如下图所示的git log
* 328dbdb (origin/master) 33333
| * 6f76c80 (HEAD -> master) 1111
|/
| * 4abed5e (origin/test) create test file
|/
* 691f18a clone1
* 7b15b7a conflict by clone 1
* cb54dc8 clone1 1111x
可以看到远程master和本地master在不同的分支,所以即便是两个master都修改了相同的文件也不会产生冲突,真正产生冲突是在手动merge阶段
git pull在拉取代码后会自动尝试合并,如果此时本地master和远程master上修改了相同的代码,那么就会产生冲突,
git会告诉你产生冲突文件,然后需要手动解决冲突
这个命令列出了当你在特定的分支上执行 git push 会自动地推送到哪一个远程分支。
它也同样地列出了哪些远程分支不在你的本地,哪些远程分支已经从服务器上移除了,还有当你执行 git pull 时哪些分支会自动合并
首先通过git remote命令查看远程仓库 默认的远程仓库的别名交 origin
然后git remote show origin 得到如下信息
* remote origin
Fetch URL: /Users/xiang/Documents/learn/gitDemo/./p14
Push URL: /Users/xiang/Documents/learn/gitDemo/./p14
HEAD branch: master
Remote branches:
master tracked
test tracked
Local branches configured for 'git pull':
master merges with remote master
test merges with remote test
Local refs configured for 'git push':
master pushes to master (up to date)
test pushes to test (up to date)
我这是在本地做实验,所以fetch和push的url都是本地的目录,它列出了推送的远程目录以及本地分支和远程分支的对应关系
仓库重命名: git remote rename oldName newName
仓库移除: git remote rm paul
有时候别人删除了远程分支但是你并不知道,你使用git log --graph --all --oneline命令看到依然后远程分支
此时你可以使用 git remote prune origin清理没有用的分支
Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。
git tag -l 'v1.8.5*'
git tag -a v1.4 -m 'comment context'
l 表示轻量级标签,a表示标注标签,一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用
标注标签可以有提交信息,可以通过使用 git show tag 查看
如果忘记打标签,后期打标签可使用
git tag -a v0.2 -m "测试版" f8b5f6c 在最后加上commitId即可
默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。
这个过程就像共享远程分支一样 - 你可以运行 git push origin [tagname]。
如果想要一次性推送很多标签,也可以使用带有 --tags 选项的 git push 命令。 这将会把所有不在远程仓库服务器上的标签全部传送到那里
删除标签:git tag -d
默认不会从远程仓库删除任何标签,需要手动删除
git push origin :refs/tags/tagName
当你在工作时, Git 会在后台保存一个引用日志(reflog),引用日志记录了最近几个月你的 HEAD 和分支引用所指向的历史。
你可以使用 git reflog 来查看引用日志
每当你的 HEAD 所指向的位置发生了变化,Git 就会将这个信息存储到引用日志这个历史记录里。
通过这些数据,你可以很方便地获取之前的提交历史。 如果你想查看仓库中 HEAD 在五次前的所指向的提交,你可以使用 @{n} 来引用 reflog 中输出的提交记录。
$ git show HEAD@{5}
你同样可以使用这个语法来查看某个分支在一定时间前的位置。 例如,查看你的 master 分支在昨天的时候指向了哪个提交,你可以输入
git show master@{yesterday}
git show 37e8efd 通过git show commitId显示提交了那些内容
值得注意的是,引用日志只存在于本地仓库,一个记录你在你自己的仓库里做过什么的日志。
其他人拷贝的仓库里的引用日志不会和你的相同;而你新克隆一个仓库的时候,引用日志是空的,因为你在仓库里还没有操作。
git show HEAD@{2.months.ago} 这条命令只有在你克隆了一个项目至少两个月时才会有用——如果你是五分钟前克隆的仓库,
那么它将不会有结果返回。
git show HEAD 显示当前commitId点的提交内容
git show HEAD^ 显示当前commitId点的第一父提交
git show HEAD^2 显示当前commitId点的第二父提交
这种情况值适用于合并后的节点 第一父提交是合并时所在的分支的最后一次提交
第二父提交是合并时的另一个分支的最后一次提交
git stash 储藏会处理工作目录的脏的状态 - 即,修改的跟踪文件与暂存改动 - 然后将未完成的修改保存到一个栈上,而你可以在任何时候重新应用这些改动
git stash list 列出所有存储的列表
git stash apply 默认恢复最新的一次stash
git stash apply stash@{2} 应用指定的存储
git stash pop 立即应用后扔掉这次stash
git commit --amend 修改最后一次提交 注意:这时候commitId会改变,这就好像是一次变基
git rebase -i commitId 从上到下的依次重演每一个提交引入的修改
在git rebase的页面中
如果删除了某次提交的信息行,那么那次提交的补丁也会消失,如果是多次提交都修改了同一个文件,那么,很可能会冲突
现将HEAD指针指向新创建的分支,然后将新分支的索引填充为本次提交的快照,最后把这次快照复制到当前分支的工作区
soft
移动本地版本库 相当于回到了 git add 之后 git commit 之前的状态
mixed
移动本地版本库
移动暂存区
相当于回到了git add 之前,只是修改了工作区的内容
hard
移动本地版本库
移动暂存区
把工作去也回退到和版本库相同的位置
相当于完全回到了上一次提交的状态
git diff -b 忽略空白比较两次提交的不同
git status -sb
git merge 选项
-Xignore-all-space 或 -Xignore-space-change 选项。 第一个选项忽略任意 数量 的已有空白的修改,第二个选项忽略所有空白修改。
git commit -a -m
fast-forward(快进)
在合并的时候,你应该注意到了"快进(fast-forward)"这个词。
由于当前 master 分支所指向的提交是你当前提交的直接上游,所以 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,
那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”
git clean 移除工作区中未被跟踪的对象
git clean -d -n
-f 表示强制
-n 表示预先演习一下,显示出将会删除那些文件
-d 表示目录 如果有目录未被跟踪则也会删除
git diff
当需要查看任意两棵树的差异时你可以使用 git diff 命令。 此命令可以查看你工作环境与你的暂存区的差异 (git diff 默认的做法),你暂存区域与你最后提交之间的差异(git diff --staged),或者比较两个 提交记录的差异(git diff master branchB)。
Git 的哲学是聪明地决定无歧义的合并方案,但是如果有冲突,它不会尝试智能地自动解决它
首先,在做一次可能有冲突的合并前尽可能保证工作目录是干净的
正常的合并流程是
1、git checkout master
2、git merge otherBranch
如果遇到冲突时,git会告诉你冲突的文件,并对这些文件打标记为冲突,此时手动的解决冲突后使用git add fileName
告诉git 这个文件的冲突已经解决了
然后使用git merge --continue告诉git继续合并
优势有些冲突只是因为空白字符产生的,git也可以忽略空白字符
git merge -Xignore-all-space otherBranch
当发生冲突时选择谁的?
git merge -Xours dev1 如果有冲突则按照我们自己的代码来即遇到冲突使用我们的覆盖别人的
git merge -Xtheirs dev1 如果有冲突则按照别人的代码来即遇到冲突使用别人的覆盖我们的
如果你想要在最终提交前看一下我们这边与另一边之间实际的修改,你可以使用 git diff 来比较将要提交作 为合并结果的工作目录与其中任意一个阶段的文件差异。 让我们看看它们。
要在合并前比较结果与在你的分支上的内容,换一句话说,看看合并引入了什么,可以运行 git diff --ours
Git 给你一个生成一个新提交的选项,提交将会撤消一个已存在提交的所有修 改。 Git 称这个操作为 "还原"
git revert HEAD 撤销前面一次提交并自动提交到本地仓库(类似于 --hard)
git revert -n HEAD 撤销前面一次提交不会提交到本地仓库 (类似于--mixed) 需要手动commit
有如下提交的分支图
* 7421d0e (HEAD -> test) 6
* 249ee95 5
* d859d07 4
* 4ae08c0 3
* 726b008 2
* 8d5d53b 1
git revert 4ae08c0..7421d0e 相当于把4-5-6全部撤销 注意:不包括(4ae08c0)即3
如果你在追踪代码中的一个 bug,并且想知道是什么时候以及为何会引入,文件标注通常是最好用的工具。
它 展示了文件中每一行最后一次修改的提交。 所以,如果你在代码中看到一个有问题的方法,
你可以使用 git blame 标注这个文件,查看这个方法每一行的最后修改时间以及是被谁修改的。
这个例子使用 -L 选项来限制输 出范围在第10至30行:
git blame -L 10,30 ModelDataController.java 找出这个文件的提交者
-L 表示要展示多少行
objects 目录存储所有数据内容;
refs 目录存储指向数据(分支)的提交对象的指针;
HEAD 文件指示目前被检出的分支;
index 文件保存暂存区信(index)
从根本上来讲 Git 是一个内容寻址(content-addressable)文件系统,并在此之上提供了一个版本控制系统的用户界面
内容寻址文件系统层是一套相当酷的东西
这意味着,Git 的核心部分是一个简单的键值对数据库(key-value data store)。 你可以向该数据库插入任意类型的内容,它会返回一个键值,通过该键值可以在任意时刻再次检索(retrieve)该内容。 可以通过底层命令 hash-object 来演示上述效果——该命令可将任意数据保存于 .git 目录,并返回相应的键值
可以看到 Git 对 objects 目录进行了初始化,并创建了 pack 和 info 子目录,但均为空。 接着,往 Git 数据 库存入一些文本:
$ echo 'test content' | git hash-object -w --stdin d670460b4b4aece5915caf5c68d12f560a9fe3e4
-w 选项指示 hash-object 命令存储数据对象;若不指定此选项,则该命令仅返回对应的键值。 --stdin 选 项则指示该命令从标准输入读取内容;若不指定此选项,则须在命令尾部给出待存储文件的路径。 该命令输出 一个长度为 40 个字符的校验和。 这是一个 SHA-1 哈希值——一个将待存储的数据外加一个头部信息 (header)一起做 SHA-1 校验运算而得的校验和。后文会简要讨论该头部信息。
$ find .git/objects -type f .git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
可以在 objects 目录下看到一个文件。 这就是开始时 Git 存储内容的方式——一个文件对应一条内容,以该内 容加上特定头部信息一起的 SHA-1 校验和为文件命名。 校验和的前两个字符用于命名子目录,余下的 38 个字符 则用作文件名
git cat-file -p 915e94ff1ac3818f1e458534b0228a12a99cd6c5
每一个文件对象,我们称之为数据对象 blob
这基本就是 Git 分支的本质:一个指向某一系列提交之首的指针或引用。
它像是一个永不移动的分支引用——永远指向同一个提交对象,只不 过给这个提交对象加上一个更友好的名字罢了
============================================