实际用到的Git命令记录总结
上传代码
$ git status
$ git add .
$ git commit -m "写一些注释"
$ git commit -am “注释” git add + git commit
$ git push origin wiriting
拉取代码
$ git pull
$ git pull origin 分支名
强制拉取并覆盖本地代码
$ git fetch --all
$ git reset --hard origin/master
$ git pull
简写:
$ git fetch --all && git reset --hard origin/master && git pull
git pull 想保留本地工作区内容
$ git stash 本地的所有修改被暂时存储起来 。用git stash list可以看到保存的信息: 其中stash@{0}就是刚才保存的标记。
$ git pull
$ git stash pop stash@{0} 还原暂存区的内容
系统若提示如下类似的信息:Auto-merging c/environ.c
CONFLICT (content): Merge conflict in c/environ.c
意思就是系统自动合并修改的内容,但是其中有冲突,需要解决其中的冲突。
打开冲突的文件,会看到类似如下的内容:
git冲突内容
其中Updated upstream 和=====之间的内容就是pull下来的内容,====和stashed changes之间的内容就是本地修改的内容。碰到这种情况,git也不知道哪行内容是需要的,所以要自行确定需要的内容。
解决完成之后,就可以正常的提交了。
Git基本原理
版本控制
记录文件的所有历史变化
错误恢复到某个历史版本
多人协作开发编辑同一个文件
Git 保存数据
Git 像是把数据看作是对小型文件系统的一系列快照。
在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。
为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。
Git 保证完整性
Git 中所有的数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。
Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。是基于 Git 中文件的内容或目录结构计算出来。
SHA-1 哈希看起来是这样:24b9da6552252987aa493b52f8696cd6d3b00373
实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。
Git 基本流程
Working Tree 当前的工作区域
Index/Stage 暂存区域,保存了下次将提交的文件列表信息
Repository 仓库,提交的历史,即使用 git commit 提交后的结果
Remote 远程仓库,git push 提交
把文件存入Repository流程图解
1. 刚开始 working tree 、 index 与 repository(HEAD)里面的內容都是一致的
2. 当git管理的文件夹里面的内容出现改变后,此時 working tree 的內容就会跟 index 及 repository(HEAD)的不一致,而Git知道是哪些文件(Tracked File)被改动过,直接将文件状态设置为 modified (Unstaged files)。
3. 当我們执行 git add 后,会将这些改变的文件內容加入 index 中 (Staged files),所以此时working tree跟index的內容是一致的,但他们与repository(HEAD)內容不一致。
4. 接着执行 git commit 後,將Git索引中所有改变的文件內容提交至 Repository 中,建立出新的 commit 节点(HEAD)后, working tree 、 index 与repository(HEAD)区域的内容又会保持一致。
Git 基本用法
1. 在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。
$ git add files - 把当前文件放入暂存区域
$ git add -A 提交所有变化
$ git add -u 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new)
$ git add . 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
$ git commit - 给暂存区域生成快照并提交
$ git reset – files - 用来撤销最后一次git commit
$ git checkout – files - 撤销对工作区的修改,以最新的存储时间节点(add和commit)为参照,覆盖工作区对应文件file;这个命令改变的是工作区
2. 跳过暂存区域直接从仓库取出文件或者直接提交代码
$ git commit -a 相当于运行 git add 把所有当前目录下的文件加入暂存区域再运行。git commit.
$ git commit files 进行一次包含最后一次提交加上工作目录中文件快照的提交。并且文件被添加到暂存区域。
$ git checkout HEAD – files 回滚到复制最后一次提交。直接用HEAD覆盖工作区、暂存区
3. 查看在上次提交之后是否有修改
加 -s 参数,以获得简短的结果输出;
如果没加该参数会详细输出内容:
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README
new file: hello.php
4. 执行 git diff 来查看执行 git status 的结果的详细信息。
$ git diff 命令显示已写入缓存与已修改但尚未写入缓存的改动的区别。
尚未缓存的改动:$ git diff
查看已缓存的改动: $ git diff --cached
查看已缓存的与未缓存的所有改动:$ git diff HEAD
显示摘要而非整个 diff:$ git diff --stat
Git Reset
我们用Git的时候有可能commit提交代码后,发现这一次commit的内容是有错误的,那么有两种处理方法修改错误内容,再次commit一次;使用git reset 命令撤销这一次错误的commit。第一种方法比较直接,但会多一次commit记录。
1. git-reset - Reset current HEAD to the specified state
( HEAD:当前分支引用的指针,总是指向该分支上的最后一次提交。这表示HEAD将是下一次提交的父节点。也可以把HEAD看作是你的上一次提交的快照。)
意思就是可以让HEAD这个指针指向其他的地方。例如我们有一次commit不是很满意,需要回到上一次的Commit里面。这个时候就需要通过reset,把HEAD指针指向上一次的commit的点。
reset有三种模式,soft,mixed,hard.
2. reset --hard 会在重置 HEAD 和branch的同时,重置stage区和工作目录里的内容, 使用此命令所有的改动都会被擦掉。
git reset --hard 版本库ID
彻底将工作区、暂存区和版本库记录恢复到指定的版本库
3. reset --soft 会在重置 HEAD 和 branch 时,保留工作目录和暂存区中的内容,并把重置 HEAD 所带来的新的差异放进暂存区。
git reset --soft 版本库ID
仅仅只是撤销已提交的版本库,不会修改暂存区和工作区
4. reset 如果不加参数,那么默认使用 --mixed 参数
git reset --mixed 版本库ID
仅仅只是撤销已提交的版本库和暂存区,不会修改工作区,就是「把所有差异都混合(mixed)放在工作目录中」。
总结:
reset 的本质:移动 HEAD 以及它所指向的 branch
实质上,reset 这个指令虽然可以用来撤销 commit ,但它的实质行为并不是撤销,而是移动 HEAD 和HEAD 所指向的 branch(如果有的话)。
而 reset --hard HEAD^ 之所以起到了撤销 commit 的效果,是因为它把 HEAD 和它所指向的 branch 一起移动到了当前 commit 的父 commit 上,从而起到了「撤销」的效果:
Git 的历史只能往回看,不能向未来看,所以把 HEAD 和 branch 往回移动,就能起到撤回 commit 的效果。
同理,reset --hard 不仅可以撤销提交,还可以用来把 HEAD 和 branch 移动到其他的任何地方。
git reset --hard branch2
使用场景:
1. --hard:
(1) 要放弃目前本地的所有改变时,可以执行 git reset -hard HEAD 来强制恢复git管理的文件夹的內容及状态;
(2) 真的想抛弃目标节点后的所有commit(可能觉得目标节点到原节点之间的commit提交都是错了,之前所有的commit有问题)。
2. --soft:
阶段性地频繁提交,就是开发一个功能的时候,改或者增加一个文件的时候就commit,这样做导致一个完整的功能可能会好多个commit点。
这时假如你需要把这些commit整合成一个commit的时候時,可以使用reset --soft来让 commit 演进线图较为清晰。总而言之,可以使用–soft合并commit节点。
3. --mixed(默认):
(1) 有时候发现add错文件到暂存区,就可以使用命令。
(2) commit提交某些错误代码,或者没有必要的文件也被commit上去,不想再修改错误再commit(因为会留下一个错误commit点),可以回退到正确的commit点上,然后所有原节点和reset节点之间差异会返回工作目录,假如有个没必要的文件的话就可以直接删除了,再commit上去就OK了。
Git分支管理
假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件。
当使用 git commit 进行提交操作时,Git 会先计算每一个子目录的校验和, 然后在 Git 仓库中这些校验和保存为树对象。
随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。 如此一来,Git 就可以在需要的时候重现此次保存的快照。
现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个 树 对象 (记录着目录结构和 blob 对象索引)以及一个 提交 对象(包含着指向前述树对象的指针和所有提交信息)。
做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。
Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。
在多次提交操作之后,其实已经有一个指向最后那个提交对象的 master 分支。 master 分支会在每次提交时自动向前移动。
Git 分支操作
创建新分支 $ git branch testing 在当前所在的提交对象上创建一个指针
分支切换
$ git checkout testing
HEAD 指向当前所在的分支
提交操作
$ git commit -a -m 'made a change'
HEAD 分支随着提交操作自动向前移动
分支切换
$ git checkout master
使 HEAD 指回 master 分支;
将工作目录恢复成 master 分支所指向的快照内容
做些修改并提交
$ git commit -a -m 'made other changes'
项目的提交历史产生分叉
查看分叉历史 $ git log --oneline --decorate --graph --all 输出提交历史、各个分支的指向以及项目的分支分叉情况
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project
Git rebase
开发进程分叉到两个不同分支,又各自提交了更新
最容易的整合分支的方法是 merge 命令,它会把两个分支最新的快照(C3 和 C4)以及二者最新的共同祖先(C2)进行三方合并,合并的结果是产生一个新的提交对象(C5)
还有另外一个选择:可以把在 C3 里产生的变化补丁在 C4 的基础上重新打一遍。在 Git 里,这种操作叫做衍合(rebase)。
有了 rebase 命令,就可以把在一个分支里提交的改变移到另一个分支里重放一遍。
$ git checkout experiment
$ git rebase master
它的原理是回到两个分支最近的共同祖先,根据当前分支(也就是要进行衍合的分支 experiment)后续的历次提交对象(这里只有一个 C3)。
生成一系列文件补丁,然后以基底分支(也就是主干分支master)最后一个提交对象(C4)为新的出发点,逐个应用之前准备好的补丁文件。
最后会生成一个新的合并提交对象(C3’),从而改写 experiment 的提交历史,使它成为 master 分支的直接下游,如图所示:
把 C3 里产生的改变到 C4 上重演一遍
远程分支
获得远程引用的完整列表 $ git ls-remote <remote>
获得远程分支的更多信息 $ git remote show <remote>
从服务器拉取数据 $ git clone
本地与远程的工作可以分叉,如果你在本地的 master 分支做了一些工作,在同一段时间内
有其他人推送提交到远程服务器并且更新了它的 master 分支,
这就是说你们的提交历史已走向不同的方向。
即便这样,只要你保持不与 origin 服务器连接(并拉取数据),你的 origin/master 指针就不会移动。
与给定的远程仓库同步数据 $ git fetch <remote>
从中抓取本地没有的数据,并且更新本地数据库,移动 origin/master 指针到更新之后的位置
推送 $ git push <remote branch>
当你想要公开分享一个分支时,需要将其推送到有写入权限的远程仓库上
拉取 $ git fetch $ git pull
git fetch 将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。
git pull 是一个 git fetch 紧接着一个 git merge 命令。 将远程主机的最新内容拉下来后直接合并。
分支使用场景
开发分支(dev)上的代码达到上线的标准后,要合并到 master 分支
$ git checkout dev
$ git pull
$ git checkout master
$ git merge dev
$ git push -u origin master
当master代码改动了,需要更新开发分支(dev)上的代码
$ git checkout master
$ git pull
$ git checkout dev
$ git merge master
$ git push -u origin dev