Git
本文是根据扔物线大神的git手册和https://git-scm.com/book/zh/v2进行整理
1.什么是版本控制系统?
Git 是一个分布式版本控制系统,Version Control System - VCS
最简化的版本控制模型,是大多数主流文本编辑器都有的「撤销(Undo)」功能:你本来想删除一个字符,却在按删除键之前不小心选中了全文,结果一下子整篇文档都被删光了,没关系,按一下「撤销」(Ctrl + Z 或 ⌘ + Z 或 U 等等,具体和你的操作系统以及编辑器有关),删掉的文字就都回来了。这其实是文本编辑器帮你自动保存了之前的内容,当你按下「撤销」的时候,它就帮你把内容回退到上一个状态;同理,按一次是会退到上一个版本,按两次就是回退到上上一个版本。
写程序的时候同样也难免会遇到「写错」的情况,所以程序的 VCS,当然也会需要版本控制功能,这样当你发现「昨天有一行代码写错了」,你就不用凭着记忆把那段代码背出来,而只需要在 VCS 中选择撤回到昨天的那个版本。
2.版本控制系统种类
中央版本控制系统,分布式版本控制系统
中央式版本控制系统(Centralized VCS)
分布式的版本控制系统(Distributed VCS)
区别
类别 | 中央式版本控制系统 | 分布式版本控制系统 |
---|---|---|
是否有本地仓库 | 无 | 有 |
是否有中央仓库 | 有 | 有 |
推送步骤 | 拉取中央版本到本地,合并本地版本,上传到中央服务器 | 拉取中央到本地仓库,合并中央版本和本地版本,上传到本地仓库,同步到中央仓库 |
3.git基本操作
安装
点击这里去下载个 Git ,安装到你的机器上。或者如果你喜欢用 Homebrew 或 apt 什么的来安装都好,总之,把它安装好。如果不会的话,请自行百度,“如何安装git",及”如何配置git环境“
装好以后,就可以正式开始上手 Git 了。
目录分析
.git --- 此目录为本地仓库,是隐藏文件
.gitignore --- git的忽略文件
LICENSE --- 协议文件不用管
clone
git clone git地址 (此命令是clone到当前目录地址)
git clone git地址 本地文件目录(此命令是clone到指定的本地文件目录)
举例:
git clone https://github.com/lvm0306/Android-ui-2018.git (该指令是拉取到本地的默认地址)
git clone https://github.com/lvm0306/Android-ui-2018.git /Users/lovesosoi/Documents/git_space/Android-ui-2018(该指令是将项目拉取到了/Users/lovesosoi/Documents/git_space/Android-ui-2018 )
github 中 创建时没有Readme,没有 LICENSE 的话,git不会自动创建 master 分支,如果有Readme和License时,git会自动创建master。
创建时自带master分支
image
创建时不带master分支
image
当push一个空项目时,没有master 分支的项目,git会自动创建一个master分支。
image
当Push 一个有master项目时,git 则会传到master上。
image
git辅助指令
git log
查看提交记录
git log -p
查看详细历史
git log --stat
查看简要统计
git status
查看本地仓库文件状态,红色是未添加,绿色是已添加,如果是本地服务器已经上传到github服务器,即本地文件与服务器文件一致的话,则显示如下文字
git show
查看具体提交的详细内容
git show commit_id
即:git show 5e68b0d8
查看某次提交的具体详情
git show commit_id xxx
即:git show 5e68b0d8 README.md
查看某次提交的README.md 的具体修改细节
git diff --staged
使用 git diff --staged 和 git diff --cached 可以显示暂存区和上一条提交之间的不同。换句话说,这条指令可以让你看到「如果你立即输入 git commit,你将会提交什么」,此两条语句的效果完全一致
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
如果本地仓库的文件状态大于github服务器的状态的话,则会显示如下文字
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
image
add
git add xxx
添加xxx文件
git add .
添加git目录下所有未添加过的文件
commit
git commit
:wq!
push
git push
git pull
冲突
push前要不pull的话,并且github服务器被他人提交过,此时是提交不成功的,会提示:如下信息
image
所以要养成好习惯,每次push前一定要pull
如果github 服务器被人提交过,并且改的文件和你改的文件一致,那么本地需要修改冲突即merge,与服务器冲突时会显示如下文字,并且告诉你需要merge的文件
image通过vim 指令查看冲突文件具体内容,
<<<<<
服务器代码
=====
本地代码
>>>>>
image
分支
创建分支
git branch test
切换分支
git checkout test
创建分支同时并且切换
git checkout -b test
在分支添加文件,上传文件时 会提示
fatal: The current branch test has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin test
这是因为git本地新建一个分支后,必须要做远程分支关联。如果没有关联, git 会在下面的操作中提示你显示的添加关联
提交分支
git push origin test
合并分支
先切换到主分支,在进行分支合并
git checkout master
git merge test
git push
删除分支
git branch -d test//删除本都test分支
git push origin -d test
//删除远程分支
删除注意
1.HEAD 指向的 branch 不能删除。如果要删除 HEAD 指向的 branch,需要先用 checkout 把 HEAD 指向其他地方。
查看所有分支
git branch -a
取回刚删除的分支
git reflog//找到branch1分支被删除前的commit c08de9a
git checkout c08de9a
git checkout -b branch1
Pull Request
提交分支后,创建一个pull request,可以让其他人查看,提交内容是否有问题,如果有问题可以继续commit,直到此次分支修改完成,点击Merge pull request
rebase(变基)与交互式变基
把你指定的 commit 以及它所在的 commit 串,以指定的目标 commit 为基础,依次重新提交一次。
换个解释:你可以提取在 分支 中引入的补丁和修改,然后在 master 的基础上应用一次。 在 Git 中,这种操作就叫做 变基。
$ git checkout test
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
$ git checkout master
$ git merge test
无论是通过变基,Merge,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。
撤销操作
撤销最新的一次操作,此处分两种情况
1,提交了但是没有push,此时撤销最新一次本地仓库提交
2,提交了,push了,此时撤销服务器的最新一次提交
解决1:
主要语句git commit --amend
举例
vim README.md
git add .
git commit -m "1"
git log
//此时log 有一条提交信息为1的,但是此时后悔了,想修改上一条提交
vim README.md
git add .
git commmit --amend
此时进入与提交语句页面,单与平常不同的是,第一行是之前的提交信息,即“1”
我们将其修改成 “2”
git log
此时提交信息为1的那条记录已经没了
解决2:
如果提交的分支是自己控制的分支(即代码都是自己可控制的)
使用git push origin branch1 -f
先用上一个解决办法,将本地库修改为正确的(此时本地库为争取的),此时提交肯定会冲突的,但是这个冲突是已知的,所以不能按照常规push 操作,需要强制push
git push origin branch1 -f
如果提交的内容已经被合并到了master 上了怎么办,此时是不能强制push的,万一覆盖了别人的代码,就等着那人提到砍你吧。
此时的操作应该是
git revert HEAD^
上面这行代码就会增加一条新的 commit,它的内容和倒数第二个 commit 是相反的,从而和倒数第二个 commit 相互抵消,达到撤销的效果。
撤下以前不知道多少次之前的一次操作
主要通过 git rebase -i 某次commit
通过git log
找到自己的需要修改commit Sha1值及commit信息
可以通过 ^
和 ~
来定位到需要修改的commit
说明:在 Git 中,有两个「偏移符号」: ^ 和 ~。
^ 的用法:在 commit 的后面加一个或多个 ^ 号,可以把 commit 往回偏移,偏移的数量是 ^ 的数量。例如:master^ 表示 master 指向的 commit 之前的那个 commit; HEAD^^ 表示 HEAD 所指向的 commit 往前数两个 commit。
~ 的用法:在 commit 的后面加上 ~ 号和一个数,可以把 commit 往回偏移,偏移的数量是 ~ 号后面的数。例如:HEAD~5 表示 HEAD 指向的 commit往前数 5 个 commit。...
eq:
git rebase -i HEAD^^ 是指倒数第二次的提交
git rebase -i 3571d777723f67
3571d777723f67 是倒数第二次的commit ShA1值
通过以上两种方式都能定位到你需要修改commit 上。
然后进入到提交界面,与之不同的是,最上边是
pick absdnm commit信息1
pick asdwqe commit信息2
将与之前记住的commit信息与之校对,找到相同的那一行,将pick 改为edit,然后保存。
会出现如下提示:证明此时rebase 已经停留在了你想修改的那一条commit上了
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
通过git commit --amend
更正
Successfully rebased and updated refs/heads/test43.
最后将修改的commit 应用上去
git rebase --continue
删除操作
删除上一条的commit
git reset --hard HEAD^
HEAD^:表示恢复到HEAD上一条(^
,~
功能上一条有讲)
或者使用
git reset --hard 8b02128e
删除到8b02128e 这条commit 之前的所有commit
删除某一条操作
比如只删除倒数第二条的数据
git rebase -i HEAD^^
然后界面如下
pick de42fd0 ic ---倒数第二条commit
pick 13fe8e3 add ---倒数第一条comit
# Rebase 512dee3..13fe8e3 onto 512dee3 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
~
我们要删除倒数第二条commit,所以删除第一行就可以了
出现如下提示,说明操作成功了,可以通过git log 查看下 倒数第二条commit 是否已经被删除了
Successfully rebased and updated refs/heads/master.
分支部分合并到master
情景如下
1-2-3-4-5-6
a-b-c-d
123456是master的commit
abcd是分支branch 的commit
1.现在需要将abcd 合并master
git rebase 第3个commit
2.现在需要将bcd合并master
git rebase --onto 第3个commit 第a个commit branch
stash
git stash
如果目前正在修改branch ,但是需要去master 改bug,而且很急,但是工作区内有内容,可以通过git stash
将工作区暂存,再去 checkout master,去修改master。
git stash pop
master bug改好了,通过git stash pop
将刚才存储的工作区的内内容取出来。
存储时如果有未add的内容,执行git stash -u
,将未add的内容也一起存储了。
checkout
当前项目做到了3.0.0版本,突然有一天,老板要2.0.0的安装包,此时你突然发现,以前的你是个傻只,没有将2.0.0建分支,也没有留过2.0.0的代码,但是你每次提交时都有一个好习惯,提交时,写了提交内容,你顺着提交记录,找到了2.0.0的最后一次提交commit。
此时只需要执行git checkout commit_Sha1
就会将该commit的代码检出来。
git checkout HEAD^^^^^^^^
git checkout master^7
以上都可以检出你需要的代码,只要能找到2.0.0的commit就可以,当然最好还是,每发一个版本,都建立相应的分支,这样以后操作也会方便不少。
reset
git reset --hard HEAD^
删除了最新的一次commit,如果当时commit 的工作区和暂存区有内容的,也会一并清除。这样并不是都满足我们的需求,我们强烈要求保留工作目录
git reset --soft HEAD^
soft会保留工作目录内容所带来的差异文件放进暂存区。
git reset HEAD^
不加参数是使用默认参数 --mixed
保留工作目录,并清空暂存区
参数 | 效果 |
---|---|
--hard | 重置位置的同时,清空工作目录的所有改动; |
--soft | 重置位置的同时,保留工作目录和暂存区的内容,并把重置 HEAD 的位置所导致的新的文件差异放进暂存区。 |
--mixed(默认) | 重置位置的同时,保留工作目录的内容,并清空暂存区。... |
.gitignore
主要分为忽略某个具体文件,忽略某个文件夹下的所有文件,忽略某一类文件
以斜杠“/”开头表示目录;
以星号“*”通配多个字符;
以问号“?”通配单个字符
以方括号“[]”包含单个字符的匹配列表;
以叹号“!”表示不忽略(跟踪)匹配到的文件或目录;
规则:fd1/*
说明:忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;
规则:/fd1/*
说明:忽略根目录下的 /fd1/ 目录的全部内容;
规则:*.dex
说明:忽略所有.dex文件
网友评论