目录
----------------------------------------------------------------------------------------------
前言:同是代码仓库,比较SVN来说GIT可以更好的管理分支。
学习git可以访问gitee的学习网站,类似游戏的引导学习,你不会失望的!
1.初次上传
git init
git add .
git commit -m "messge"
git remote add origin 地址
git pull --rebase origin master
git push -u origin master git status
2.删除git文件不删除本地
// 无法提交时尝试清除缓存
git rm -r --cached filepath
git commit -m "del"
git push
3.查看配置
git config -l
git remote -v
git config -global user.name "xxx"
git remote rm xxx
1.分支创建/切换
git branch
git branch new_branch
git checkout (-b) new_branch (-b参数表示先创建再切换)
git commit
2.分支合并
git branch bugFix
git checkout bugFix
git commit -m "c2"
git checkout master
git commit -m "c3"
git merge bugFix (当前分支 *master)
git checkout bugFix
git merge master
第二种合并分支的方法是 git rebase。Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。
Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。
git checkout -b bugFix
git commit
git checkout master
git commit
git checkout bugFix
git rebase master
git checkout master
git commit
HEAD: 当前检出记录的符号引用,也就是指向正在其基础上进行工作的提交记录。HEAD总是指向当前分支上最近一次提交记录。
大多数修改提交树的Git命令都是从改变HEAD的指向开始的。
HEAD通常情况下使指向分支名的(如bugFix)。在提交时,改变了bugFix状态,这一变化通过HEAD变得可见。
cat .git/HEAD (查看HEAD指向)
分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。
在命令执行之前的状态如下所示:
HEAD -> master -> C1
HEAD 指向 master, master 指向 C1
执行 git checkout c1 之后,变成:
HEAD -> c1(哈希值)
相对引用:
通过指定提交记录哈希值的方式在 Git 中移动不太方便。在实际应用时,并没有像本程序中这么漂亮的可视化提交树供你参考,所以你就不得不用 git log 来查查看提交记录的哈希值。 并且哈希值在真实的 Git 世界中也会更长(译者注:基于 SHA-1,共 40 位)。例如前一关的介绍中的提交记录的哈希值可能是 fed2da64c0efc5293610bdd892f82a58e8cbc5d8。舌头都快打结了吧... 比较令人欣慰的是,Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2 而不是上面的一长串字符。
操作符 (^)。把这个符号加在引用名称的后面,表示让 Git 寻找指定提交记录的父提交。 所以 master^ 相当于“master 的父节点”。 master^^ 是 master 的第二个父节点。
也可以将 HEAD 作为相对引用的参照。下面咱们就用 HEAD 在提交树中向上移动几次。
“~”操作符 如果你想在提交树中向上移动很多步的话,敲那么多 ^ 貌似也挺烦人的,Git 当然也考虑到了这一点,于是又引入了操作符 ~。 该操作符后面可以跟一个数字(可选,不跟数字时与 ^ 相同,向上移动一次),指定向上移动多少次。
git checkout HEAD~4
可以直接使用 -f 选项让分支指向另一个提交。
例如: git branch -f master HEAD~3
上面的命令会将 master 分支强制指向 HEAD 的第 3 级父提交。
使用 HEAD/哈希引用可以灵活的改变在提交树上的提交位置
撤销变更
在 Git 里撤销变更的方法很多。和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。
主要有两种方法用来撤销变更:
方式一.git reset:
git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。
git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
git reset HEAD~1
方式二.git revert
虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的哦!
为了撤销更改并分享给别人,我们需要使用 git revert。
git revert HEAD
奇怪!在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录 C2' 引入了更改 —— 这些更改刚好是用来撤销 C2 这个提交的。
也就是说 C2' 的状态与 C1 是相同的。 revert 之后就可以把你的更改推送到远程仓库与别人分享啦。
提交、分支以及在提交树上移动。 这些概念涵盖了 Git 90% 的功能,同样也足够满足开发者的日常需求 然而, 剩余的 10% 在处理复杂的工作流时(或者当你陷入困惑时)可能就显得尤为重要了。
接下来要讨论的这个话题是“整理提交记录” —— 开发人员有时会说“我想要把这个提交放到这里, 那个提交放到刚才那个提交的后面”, 而接下来就讲的就是它的实现方式,非常清晰、灵活,还很生动。
整理提交记录
本系列的第一个命令是 git cherry-pick, 命令形式为:
git cherry-pick <提交号>...
如果你想将一些提交复制到当前所在的位置(HEAD)下面的话, Cherry-pick 是最直接的方式了。
git cherry-pick c2 c4
当你知道你所需要的提交记录(并且还知道这些提交记录的哈希值)时, 用 cherry-pick 再好不过了 —— 没有比这更简单的方式了。
但是如果你不清楚你想要的提交记录的哈希值呢? 幸好 Git 帮你想到了这一点, 我们可以利用交互式的 rebase —— 如果你想从一系列的提交记录中找到想要的记录, 这就是最好的方法了。
交互式 rebase 指的是使用带参数 --interactive
的 rebase 命令, 简写为 -i
如果你在命令后增加了这个选项, Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。
在实际使用时,所谓的 UI 窗口一般会在文本编辑器 —— 如 Vim —— 中打开一个文件。
当 rebase UI界面打开时, 你能做3件事:
a.调整提交记录的顺序(通过鼠标拖放来完成)
b.删除你不想要的提交(通过切换 pick 的状态来完成,关闭就意味着你不想要这个提交记录)
c.合并提交。
git rebase -i HEAD~4
Git其实是复制了目标的提交记录
本地栈式提交
来看一个在开发中经常会遇到的情况:我正在解决某个特别棘手的 Bug,为了便于调试而在代码中添加了一些调试命令并向控制台打印了一些信息。
这些调试和打印语句都在它们各自的提交记录里。最后我终于找到了造成这个 Bug 的根本原因,解决掉以后觉得沾沾自喜!
最后就差把 bugFix
分支里的工作合并回 master
分支了。你可以选择通过 fast-forward 快速合并到 master
分支上,但这样的话 master
分支就会包含我这些调试语句了。
实际我们只要让 Git 复制解决问题的那一个提交记录就可以了。跟之前我们在“整理提交记录”中学到的一样,我们可以使用 git rebase -i / git cherry-pick 来达到目的。
git checkout master
git cherry-pick c4
提交的技巧 #1
接下来这种情况也是很常见的:
你之前在 newImage 分支上进行了一次提交,然后又基于它创建了 caption 分支,然后又提交了一次。
此时你想对的某个以前的提交记录进行一些小小的调整。比如设计师想修改一下 newImage 中图片的分辨率,尽管那个提交记录并不是最新的了。
我们可以通过下面的方法来克服困难:
- 先用
git rebase -i
将提交重新排序,然后把我们想要修改的提交记录挪到最前 - 然后用
commit --amend
来进行一些小修改 - 接着再用
git rebase -i
来将他们调回原来的顺序 - 最后我们把 master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!
正如你在上一关所见到的,我们可以使用 rebase -i
对提交记录进行重新排序。只要把我们想要的提交记录挪到最前端,我们就可以很轻松的用 --amend
修改它,然后把它们重新排成我们想要的顺序。
但这样做就唯一的问题就是要进行两次排序,而这有可能造成由 rebase 而导致的冲突。下面还是看看 git cherry-pick
是怎么做的吧。
要在心里牢记 cherry-pick 可以将提交树上任何地方的提交记录取过来追加到 HEAD 上(只要不是 HEAD 上游的提交就没问题)。
git checkout master
git commit --amend
git cherry-pick c3
Git Tags
相信通过前面的学习你已经发现了:分支很容易被人为移动,并且当有新的提交时,它也会移动。分支很容易被改变,大部分分支还只是临时的,并且还一直在变。
你可能会问:有没有什么可以永远指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug 或是增加了某些新特性,有没有比分支更好的可以永远指向这些提交的方法呢?
当然有了!Git 的 tag 就是干这个用的啊,它们可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。
更难得的是,它们并不会随着新的提交而移动。你也不能检出到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。
git tag c1 v0
git tag c2 v1
git checkout c2
Git Describe
由于标签在代码库中起着“锚点”的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe
!
Git Describe 能帮你在提交历史中移动了多次以后找到方向;当你用 git bisect
(一个查找产生 Bug 的提交记录的指令)找到某个提交记录时,或者是当你坐在你那刚刚度假回来的同事的电脑前时, 可能会用到这个命令。
git describe
的语法是:
git describe <ref>
<ref>
可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会以你目前所检出的位置(HEAD
)。
它输出的结果是这样的:
<tag>_<numCommits>_g<hash>
tag
表示的是离 ref
最近的标签, numCommits
是表示这个 ref
与 tag
相差有多少个提交记录, hash
表示的是你所给定的 ref
所表示的提交记录哈希值的前几位。
当 ref
提交记录上有某个标签时,则只输出标签名称。
更多git学习可以访问:https://oschina.gitee.io/learn-git-branching/