1. 基本指令(重点)
创建版本仓库:创建一个文件夹,cmd执行该文件夹,然后执行
git init
即可得到.git目录
保存仓库的所有内容
新增文件:在文件夹中创建文件:xxx.txt。
执行git add xx.txt
在暂存区中新增这个文件,也可以在用空格隔开,增加多个文件,比如git add xx.txt xx2.txt
,还可以一次增加库目录中所有文件git add .
提交文件:git commit -m "this is a test file"
【-m后是对本次提交的描述】【提交添加的是所有文件】
git commit hello.txt hello2.txt -m "this is a test file"
提交某些文件
git commit -a -m "this is a test file"
自动add并commit所有已跟踪并修改或删除的文件
文件状态:git ststus
在提交后,如果文件有改动,可以看到
文件改动:git diff hello.txt
查看该文件的改动情况
注意:每次对库中内容改动后,都需要add和commit操作,同步git,git中会记录当前仓库的快照(版本)
删除文件:
git rm hello.txt
并git commit hello.txxt -m xxx
即可
帮助:
git hello commit
或git commit --help
2. 日志 - 提交历史(重点)
每次commit,随着版本的记录,也会留下日志
每次执行git log
# 显示从最早的提交点 到 当前提交点的日志
git log --oneline
# 简洁日志显示
git log --oneline -2
# 简洁日志显示,最近两次提交日志
git log --oneline --graph
# 图形化显示分支走向
注意git的
commitID
是通过SHA1计算出来的一个非常大的数字,用十六进制表示,在分布式中保证唯一
3. 版本回退(了解)
每次的修改文件并add、commit。git中也会记录一个版本,如果有需要可以回退到之前的一个数据版本状态
执行:
git resset --hard HEAD~
# 回退到上一个版本
git reset --hard HEAD~~
# 回退到上上个版本
git reset --hard HEAD~5
# 回退到上5个版本
执行:
git reset --head e475a
#回退到commitID为为”e475a…“ 的版本,commitID可以致谢前几位,唯一即可
e475afc93c209a690c39c13a46716e8fa000c366=commitID, e475a是commitID的前几位
总结:
- 每次commit,git都会保留一个版本,每个版本都有一个全局唯一的commitID
- git有个游标(指针)
HEAD
,指向当前版本,所以可以移动游标来回退版本 - 也可以通过commitID回退到某个版本
- 回退并不会删除任何版本,所以版本见可以来回切换
细节:发生版本回退后,通过
git log
只能看到最原始提交点 至 当前提交点的日志。git reflog
可以看到全部日志
4. git结构组成(重点)
仓库:执行了
git init
的目录(文件夹)
版本库:工作区中有一个隐藏目录
.git
,这个目录不属于工作区。而是git的版本库
,是git管理的所有内容
暂存区:版本库中包含一个临时区域,保存下一步要提交的文件。
分支:版本库中包含若干分支,提交的文件存储在分支中
文件首先出现在工作区,如果需要git管理,则通过git add xx
将文件添加到暂存区
通过git commit....
将暂存区的文件一次性去交到分支
中
关于分支
是git的一个重要概念,后面叙述,maste分支是安装git时默认的
5 文件状态(重点)
切换到某分支,在工作区操作其文件,文件的状态会有如下可能:
· 未跟踪
- 工作区中新创建的文件,git中并未保存它的任何记录
- git add增加到暂存时,即可建立跟踪
· 修改- 已跟踪的文件,在工作区被修改了。
· 暂存- git add 的文件,处于暂存状态。
- 每次暂存的是文件当前的状态,如果暂存后又做了修改,需要再次git add文件
- 每次提交时,是将所有暂存的文件提交。
· 提交- git commit 的文件,处于提交状态
- 每次提交,增加一个快照版本,分支指针后羿,指向最新版本
6. 文件状态查看
在工作区中一系列操作后,要查看文件状态:
执行:
git status
可以看到文件状态:
On branch master #分支 master
Changes to be committed:#说明有内容在暂存区可以提交
(use “git reset HEAD …” to unstage)
modified: hello.txt
On branch master #分支 master
Changes to be committed:#说明有内容在暂存区可以提交
(use “git reset HEAD …” to unstage)
modified: hello.txt
Changes not staged for commit:
#说明有内容没有增加到暂存区
(use “git add …” to update what will be committed)
(use “git checkout – …” to discard changes in working directory)
modified: hello.txt
细节:通过
git diff
比对变动情况:
git diff hello10.txt
比对工作区和暂存区(若暂存区没有,比分支)
git diff HEAD -- hello10.txt
比对工作区和分支中的最新结果 ( 了解或忽略此点 )
git diff --staged hello10.txt
对比暂存和分支中的最新结果 ( 了解或忽略此点 )
坑:-- hello10.txt
之间需要分隔,不能写成--hello10.txt
7. 撤消修改(了解)
如果在工作区文件中添加了如下一行,你突然意识到饭碗可能不保,所以需要撤销修改
...
My stupid boss still prefers SVN.
执行:
git checkout -- hello9.txt
可以撤销到最近一次git add 或 git commit
的状态即:如果 暂存区有此文件,则将暂存区中的文件内容恢复到工作区。 如果 暂存区没有此文件,则将分支中的文件内容恢复到工作区。
注意:
-- hello9.txt
一定不能少写--
,否则就是其他语意啦。
如果在工作区中修改了文件并发送到暂存区中,但文件中有需要撤销的内容
则可以执行:
git reset HEAD hello9.txt
将hello.txt在暂存区的内容清除。然后可执行:
git checkout -- hello9.txt
回退到上一个版本
8. 分支(重点)
就是一条时间线,线上每个店都是一起提交,都记录了当时的文件快照。
概述
- 默认有一个分支master。
- 分支中接收git commit提交的内容,为一个一个不短向前发展的提交点。每个提交点都保存一个代码版本。
- 每个分支,都有一个指针,指针默认指向最近一次提交的版本。
- 工作区中的内容,初始状态,就是指针指向的版本状态。
- 基于指针指向的版本代码,在工作区中做进一步的编码,功能完成后,即可git commit,在分支中形成新的提交点,指针也向后移一步
- 然乎再在工作区中,添加新代码,功能完成,再git commit,又形成新的提交点,指针再次后移。如此反复,不短记录版本
- 当有需要时,可以回退指针到某个提交点,在工作区中即可得到之前的某个版本的代码
9. 多分之使用
情景1:在编写一个功能时,需要一周的时间,在一周之间可能会有多次提交,但最后却发现有问题,那这些有问题的提交点就掺杂在master分支中。使master分支很混乱;
情景2:在编译一个功能时,有一个临时的思路,但不确定能否最终实现预期功能,只能试着编写,最后发现不成立,则提交过的所有提交点都无效,也会掺杂在master分支中。
而且如果是多人协同开发,有可能影响到其他人的开发进度。
实际开发中master分支我们只愿意存放稳定的代码提交,保证master分支稳定,有效
方案一:一直不提交,等所有都写完以后,提交一次。虽然可以保护master分支,但开发过程中缺乏版本控制点,易丢失工作。
方案二:在需要编写新功能时,新建一个开发用的分支,所有改动都在改分支上提交,在功能完整实现后,将该分支的最终内容合并到master分支,这样,既保证开发中有多个版本可以控制,有保证master分支是稳定,有效的
10. 创建,切换分支
在某个库目录中,执行:
`执行`:git branch new_branch #创建分支,会和当前分支保持同样的数据状态,即新分支和当前分支指向同一个提交点
`执行`:git checkout new_branch #切换分支,工作区中显示当前分支的内容。( 切换分支,实际只是在切换指针 )
`执行`:git branch #查看当前分支
git branch -vv #查看分支详细信息( 分支信息,所跟踪的远程分支信息,是否领先远程分支等 )
11. 合并 - 删除
新分支改动完成后,切换到master分支:
执行 :git branch master
#切换到master分支
执行:git merge newBr
#合并newBr分支
如上就进行了合并,此次合并就是将master的指针移向了newBr的位置==快速合并
合并后,新分支如果不再使用,可以删除(了解)
git branch --merged
#查看被当前分支合并了的分支(ops:删除分支前,先确定其已经被合并,保证工作不丢失)
git branch -d newBr
#删除newBr分支
12. 冲突 - 解决
场景:
- 创建分支。分支见图1
- 切换新的分支,并在文件最后添加“hello CHINA”,然后提交。分支图2
- 切换回master分支,并在文件最后添加“hello china”后提交。分支图3
- 在master分支中合并newBr分支。合并中出现冲突。分支图4
冲突点:两个分支对同一个文件都做了改动,所以在合并时git会无法确定保留那个分支的改动。
执行:git merge newBr
时,提示:
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.
#合并出现冲突后,git将双方的修改都保留了,并且用 <<<< ====== >>>>> 做了分隔
hello world
<<<<<<< HEAD
hello china
=======
hello CHINA
>>>>>>> newBr
此时就需要认为手工修改,比如我们最终改为hello China
#手动改为如下:
hello world
hello China
执行git add hello.txt
git commit hello.txt -m "confict handle"
# 重新提交
执行:git branch -d newBr
#如果分支不再使用,删除心分支即可
执行:git merge --abort
#中止合并,发生冲突时可以选择撤销本次合并
执行:git merge dev2 -Xignore-all-space
#避免因为空白导致冲突(了解)
13. 快照
git 在保存每个版本时(对应提交点),并不是赋值所有文件,没有改动的文件只是记录一个链接