[关闭]
@lovesosoi 2018-12-12T14:28:48.000000Z 字数 6842 阅读 749

Git

git


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

  1. git clone git地址 (此命令是clone到当前目录地址)
  2. git clone git地址 本地文件目录(此命令是clone到指定的本地文件目录)
  3. 举例:
  4. git clone https://github.com/lvm0306/Android-ui-2018.git (该指令是拉取到本地的默认地址)
  5. 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分支

创建时不带master分支

当push一个空项目时,没有master 分支的项目,git会自动创建一个master分支。

当Push 一个有master项目时,git 则会传到master上。

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,你将会提交什么」,此两条语句的效果完全一致

  1. Your branch is up to date with 'origin/master'.
  2. nothing to commit, working tree clean

如果本地仓库的文件状态大于github服务器的状态的话,则会显示如下文字

  1. Your branch is ahead of 'origin/master' by 1 commit.
  2. (use "git push" to publish your local commits)

add

git add xxx
添加xxx文件
git add .
添加git目录下所有未添加过的文件

commit

git commit

:wq!

push

git push

git pull

冲突

push前要不pull的话,并且github服务器被他人提交过,此时是提交不成功的,会提示:如下信息

所以要养成好习惯,每次push前一定要pull

如果github 服务器被人提交过,并且改的文件和你改的文件一致,那么本地需要修改冲突即merge,与服务器冲突时会显示如下文字,并且告诉你需要merge的文件

通过vim 指令查看冲突文件具体内容,

  1. <<<<<
  2. 服务器代码
  3. =====
  4. 本地代码
  5. >>>>>

分支

创建分支

git branch test

切换分支

git checkout test

创建分支同时并且切换

git checkout -b test

在分支添加文件,上传文件时 会提示

  1. fatal: The current branch test has no upstream branch.
  2. To push the current branch and set the remote as upstream, use
  3. git push --set-upstream origin test

这是因为git本地新建一个分支后,必须要做远程分支关联。如果没有关联, git 会在下面的操作中提示你显示的添加关联

提交分支

git push origin test

合并分支

先切换到主分支,在进行分支合并

  1. git checkout master
  2. git merge test
  3. git push
删除分支

git branch -d test//删除本都test分支
git push origin -d test//删除远程分支

删除注意

1.HEAD 指向的 branch 不能删除。如果要删除 HEAD 指向的 branch,需要先用 checkout 把 HEAD 指向其他地方。

查看所有分支

git branch -a

取回刚删除的分支
  1. git reflog//找到branch1分支被删除前的commit c08de9a
  2. git checkout c08de9a
  3. git checkout -b branch1

Pull Request

提交分支后,创建一个pull request,可以让其他人查看,提交内容是否有问题,如果有问题可以继续commit,直到此次分支修改完成,点击Merge pull request

rebase(变基)与交互式变基

把你指定的 commit 以及它所在的 commit 串,以指定的目标 commit 为基础,依次重新提交一次。
换个解释:你可以提取在 分支 中引入的补丁和修改,然后在 master 的基础上应用一次。 在 Git 中,这种操作就叫做 变基。

  1. $ git checkout test
  2. $ git rebase master
  3. First, rewinding head to replay your work on top of it...
  4. Applying: added staged command
  5. $ git checkout master
  6. $ git merge test

无论是通过变基,Merge,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。

撤销操作

撤销最新的一次操作,此处分两种情况

1,提交了但是没有push,此时撤销最新一次本地仓库提交
2,提交了,push了,此时撤销服务器的最新一次提交

解决1:
主要语句git commit --amend
举例

  1. vim README.md
  2. git add .
  3. git commit -m "1"
  4. git log
  5. //此时log 有一条提交信息为1的,但是此时后悔了,想修改上一条提交
  6. vim README.md
  7. git add .
  8. git commmit --amend
  9. 此时进入与提交语句页面,单与平常不同的是,第一行是之前的提交信息,即“1
  10. 我们将其修改成 2
  11. git log
  12. 此时提交信息为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:

  1. git rebase -i HEAD^^ 是指倒数第二次的提交
  2. git rebase -i 3571d777723f67
  3. 3571d777723f67 是倒数第二次的commit ShA1

通过以上两种方式都能定位到你需要修改commit 上。
然后进入到提交界面,与之不同的是,最上边是

  1. pick absdnm commit信息1
  2. pick asdwqe commit信息2

将与之前记住的commit信息与之校对,找到相同的那一行,将pick 改为edit,然后保存。
会出现如下提示:证明此时rebase 已经停留在了你想修改的那一条commit上了

  1. You can amend the commit now, with
  2. git commit --amend
  3. Once you are satisfied with your changes, run
  4. git rebase --continue

通过git commit --amend更正

  1. Successfully rebased and updated refs/heads/test43.

最后将修改的commit 应用上去

  1. git rebase --continue

删除操作

删除上一条的commit
  1. git reset --hard HEAD^

HEAD^:表示恢复到HEAD上一条(^,~功能上一条有讲)
或者使用

  1. git reset --hard 8b02128e

删除到8b02128e 这条commit 之前的**所有**commit

删除某一条操作

比如只删除倒数第二条的数据

  1. git rebase -i HEAD^^

然后界面如下

  1. pick de42fd0 ic ---倒数第二条commit
  2. pick 13fe8e3 add ---倒数第一条comit
  3. # Rebase 512dee3..13fe8e3 onto 512dee3 (2 commands)
  4. #
  5. # Commands:
  6. # p, pick = use commit
  7. # r, reword = use commit, but edit the commit message
  8. # e, edit = use commit, but stop for amending
  9. # s, squash = use commit, but meld into previous commit
  10. # f, fixup = like "squash", but discard this commit's log message
  11. # x, exec = run command (the rest of the line) using shell
  12. # d, drop = remove commit
  13. #
  14. # These lines can be re-ordered; they are executed from top to bottom.
  15. #
  16. # If you remove a line here THAT COMMIT WILL BE LOST.
  17. #
  18. # However, if you remove everything, the rebase will be aborted.
  19. #
  20. # Note that empty commits are commented out
  21. ~

我们要删除倒数第二条commit,所以删除第一行就可以了
出现如下提示,说明操作成功了,可以通过git log 查看下 倒数第二条commit 是否已经被删除了

  1. Successfully rebased and updated refs/heads/master.

分支部分合并到master

情景如下

  1. 1-2-3-4-5-6
  2. a-b-c-d

123456是master的commit
abcd是分支branch 的commit
1.现在需要将abcd 合并master

  1. git rebase 3commit

2.现在需要将bcd合并master

  1. git rebase --onto 3commit acommit 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

主要分为忽略某个具体文件,忽略某个文件夹下的所有文件,忽略某一类文件

  1. 以斜杠“/”开头表示目录;
  2. 以星号“*”通配多个字符;
  3. 以问号“?”通配单个字符
  4. 以方括号“[]”包含单个字符的匹配列表;
  5. 以叹号“!”表示不忽略(跟踪)匹配到的文件或目录;

规则:fd1/*
说明:忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;
规则:/fd1/*
说明:忽略根目录下的 /fd1/ 目录的全部内容;
规则:*.dex
说明:忽略所有.dex文件

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注