码迷,mamicode.com
首页 > 其他好文 > 详细

git

时间:2019-07-21 14:59:48      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:有一个   邮箱   注释   原来   stash   git clone   点击   注意   核心   

git init

git init命令把这个目录变成Git可以管理的仓库,在该目录下就会多出.git目录

使用ls -ah就可以看见

默认是master分支

git commit

git commit命令,-m后面输入的是本次提交的说明

执行成功后:

1 file changed:1个文件被改动(我们新添加的readme.txt文件);2 insertions:插入了两行内容(readme.txt有两行内容)。

合并commit add

git commit -am "注释"

git log

git log命令显示从最近到最远的提交日志

可以加上--pretty=oneline

 $ git log --pretty=oneline
 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
 e475afc93c209a690c39c13a46716e8fa000c366 add distributed
 eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file

git reflog 看回退日志的

git reset

  • HEAD指向的版本就是当前版本,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id

  • git reset --hard head^^

  • git reset --hard head~n

  • git log可以查看提交历史,以便确定要回退到哪个版本。

  • git reflog查看命令历史,以便确定要回到未来的哪个版本。

工作区和暂存区

.git属于Git的版本库

Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

git add把文件添加进去,实际上就是把文件修改添加到暂存区;

git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支本地库(对象区)。

git push 将本地库(对象区)里的推送到远程库

撤销修改

git checkout -- file可以丢弃工作区的修改

命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。


git reset HEAD <file>可以把暂存区的修改撤销掉(unstage),重新放回工作区

git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。


场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,第二步按场景1操作。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,git reset,不过前提是没有推送到远程库。

删除文件

文件管理器中把没用的文件删了,或者用rm命令删了

这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了

 $ git status
 On branch master
 Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 ?
  deleted:   test.txt
 ?
 no changes added to commit (use "git add" and/or "git commit -a")

现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

git checkout 用于版本穿梭就处于游离状态:

1.回到以前版本,修改后必须提交

2.看提示,创建分支,利用git提示的id 作为 分支指向版本的哈希码

推送到远程库

在本地仓库下运行命令:

git remote add [别名] [远程地址]

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

git push [别名] [分支名]

分支概念(建议将分支理解为指针)

版本是主线,而分支只是指向版本的指针.commit链

新建分支的命令是基于当前所在分支的基础上进行的,即以上是基于mater 分支新建了一个叫做 develop 的分支,此时 develop 分支跟 master 分支的内容完全一样.及master指针和develop指针指向同一个commit版本.

每次commit后,当前分支(指针)就指向commit后的版本.

删除分支,建议先将要删除的分支合并到其他分支上

删除分支命令:git branch -d 分支名(不能删除当前分支)

创建新分支并切换到新建分支:git checkout -b 分支名

git branch -D 强删


你在切换分支的时候,你可以看到你的工作区的文件的变化的.

如果在分支a进行了写操作,但此操作并没有 add,commit(局限在工作区) ,在master里面是可以看到这个文件的.如果在分支a中进行了写操作,进行了commit(对象区),则master里面是无法看到这个文件的.

如果在分支a进行了写操作,但此操作并没有 add,commit(局限在工作区) ,删除分支a是可以成功的.


如果一个分支版本靠前(dev),一个分支版本靠后(master).如果不冲突,master可以通过merge 直接追赶上 dev ,称为fast forward

本质:跳过中间的commit,依然会保存(跳过中间的版本),然后两个分支会指向同一个版本,并且丢失主动合并的那条分支信息

注意:git在merge 的时候,默认使用fast forward,也可以禁止:git merge --no -f 分支名

这个时候两个分支不会指向同一个版本,主动合并的分支会指向合并后创建的新的版本.

不会丢失主动合并的那条分支信息.

技术图片

技术图片


分支重命名:

git branch -m 原分支名 修改后的分支名


git branch -av 可以查看本地和远程有哪些分支

如果远程没有本地的分支,将本地的分支往远程推:git push --set-upsteam origin 分支名

git push -u origin 分支名

而如果本地没有远程的分支,你直接pull会直接拉取到本地的追踪分支,也就是你 查看后的红字部分.

所以你就得将追踪分支的内容拉去到本地:git checkout -b 分支名 追踪分支名

git checkout -b --track 追踪分支名

你不写本地分支名,他就默认把你追逐分支名直接拉取到本地分支.

删除远程分支 git push origin --delete 分支名

git 合并冲突产生原因

git分支 master 修改某个文件并提交后,master分支的版本就要相对与g1分支要早一步,然后切换到g1分支.g1分支下修改同一文件的同一位置,然后提交,然后合并分支时,就会产生冲突.

相对于svn,git不会产生多于的文件.

技术图片

然后就用vim修复就可以了!

快照(version)

每次提交后的所有文件就是一次快照.

stash 保存现场

如果还没将某一个功能开发完毕,就要切换分支:建议1.保存现场(临时保存,stash) 2.切换

保存现场:git stash

还原现场:git stash pop(将原来保存的内容删除,用于还原现场)

git stash apply (还原内容,不删除原来的内容)

查看现场:git stash list

github详解

技术图片

Issues

代表该项目的一些问题或者 bug,并不是说 Issues 越少越好,Issues 被解决的越多说 明项目作者或者组织响应很积极,也说明该开源项目的作者很重视该项目.

大家在使用一些开源项目有问题的时候都可以提 Issue,可以通过点击右上角的 New Issue 来新建 Issue,需要添加一个标题与描述就可以了,这个操作很简单。

Pull requests

参与开源项目的方式:

点击某个项目右上角的 Fork 按钮,然后该项目就出现在了你自己账号的 Repository 里。

可以看到 Fork 过来的项目标题底部会显示一行小字:fork from xxxxx

项目代码跟原项目一模一样,对于原项目来说,相当于别人新建了一个分支而已。

第二步,把该项目 clone 到本地,然后修改的 bug 也好,想要新增的功能也好,总之把自己 做的代码改动开发完,保存好。

接着,把自己做的代码改动 push 到 你自己的 GitHub 上去。第三步,点击你 Fork 过来的项目主页的 Pull requests 页面,点击 New pull request 按钮,可以看到自己添加了些什么东西,然后点击中间的 Create pull request 按钮,至此我们就成功给该项目提交了一个 PR。然后就等着项目原作者 review 你的代码,并且决定会不会接受你的 PR,如果接受,那么恭喜你,你已经是该项目的贡献者之一了。

projects:

这个项目就是方便你把一些 Issues、Pull requests进行分类,反正我觉得该功能很鸡肋

忽略:ignore

在工作区内创建.gitignore文件,在文件内填写要忽略的文件名

文件夹表示:dir/

统配符表示:*.xxx x.*

dir/*/

dir/**/ :忽略任一级

ssh协议

https 和 SSH 的区别:

1、前者可以随意克隆github上的项目,而不管是谁的;而后者则是你必须是你要克隆的项目的拥有者或管理员,且需要先添加 SSH key ,否则无法克隆。

2、https url 在push的时候是需要验证用户名和密码的;而 SSH 在push的时候,是不需要输入用户名的,如果配置SSH key的时候设置了密码,则需要输入密码的,否则直接是不需要输入密码的。

创建一个 SSH key

 ssh-keygen -t rsa -C "your_email@example.com"

代码参数含义:

-t 指定密钥类型,默认是 rsa ,可以省略。 -C 设置注释文字,比如邮箱。 -f 指定密钥文件存储文件名。

以上代码省略了 -f 参数,因此,运行上面那条命令后会让你输入一个文件名,用于保存刚才生成的 SSH key 代码

id username...技术图片

技术图片

push pull

如果本地库落后于远程库的版本.建议先pull拉取合并再push,不然,你也push不了.

记住,如果你pull下来后解决了冲突一定要告诉git你解决了冲突 git add xxxxx

注意:add后会进行两次提交,1次是最终提交,1次是将对方分支的提交信息commit也拿来了.

pull=fecth+merge

Tag标签

要我理解,就是你搞个tag 版本号去指向某个commit,不管那条commit线上有多少个一级推送到本地库或者远程库里面了,只要你吧tag推送上去,别人就会知道,当前tag指向的commit是多少版本的.因为commit是一个sha1值,一般人看不懂.

tag是git版本库的一个标记,指向某个commit的指针。

tag主要用于发布版本的管理,一个版本发布之后,我们可以为git打上 v.1.0.1 v.1.0.2 ...这样的标签。

tag感觉跟branch有点相似,但是本质上和分工上是不同的:

tag 对应某次commit, 是一个点,是不可移动的。 branch 对应一系列commit,是很多点连成的一根线,有一个HEAD 指针,是可以依靠 HEAD 指针移动的。 所以,两者的区别决定了使用方式,改动代码用 branch ,不改动只查看用 tag。 tag 和 branch 的相互配合使用,有时候起到非常方便的效果,例如:已经发布了 v1.0 v2.0 v3.0 三个版本,这个时候,我突然想不改现有代码的前提下,在 v2.0 的基础上加个新功能,作为 v4.0 发布。就可以检出 v2.0 的代码作为一个 branch ,然后作为开发分支。

适用于整个项目,和具体的分支没关系

git tag xxx git tag -a xxx -m "xxxx" 查看标签git tag 删除标签 git tag -d 标签名

git tag

git tag v1.0 简单标签,只存储当前的commit的sha1值 git tag -a v2.0 -m "我的v.2.0版本" (创建一个新对象,会产生一个新的commit/sha1)存储信息,其中包含了当前的commit的sha1值

v1.0 : 8c3512547 v2.0 : aaaa(8c3512547)

推送标签

git push origin v1.0 v2.0

git push origin --tags

git push origin v1.0 完整git push origin refs/tags/v1.0:refs/tags/v1.0

获取远程标签

git pull :如果远端新增标签,则pull 可以将新增的标签拉去到本地;如果远程是删除标签,则pull无法感知 git fetch orgin tag v4.0

删除远程标签 git push origin :refs/tags/v1.0

注意:如果将远程标签删除,其他用户无法直接感知

Git Submodule

项目的版本库在某些情况虾需要引用其他版本库中的文件,例如公司积累了一套常用的函数库,被多个项目调用,显然这个函数库的代码不能直接放到某个项目的代码中,而是要独立为一个代码库,那么其他项目要调用公共函数库该如何处理呢?分别把公共函数库的文件拷贝到各自的项目中会造成冗余,丢弃了公共函数库的维护历史,这显然不是好的方法。

git submodule add <url> <path> url为子模块的路径,path为该子模块存储的目录路径。

执行成功后,git status会看到项目中修改了.gitmodules,并增加了一个新文件(为刚刚添加的路径)

git diff --cached查看修改内容可以看到增加了子模块,并且新文件下为子模块的提交hash摘要

git commit提交即完成子模块的添加

例:

 $ git submodule add https://github.com/chaconinc/DbConnector
 Cloning into ‘DbConnector‘...
 remote: Counting objects: 11, done.
 remote: Compressing objects: 100% (10/10), done.
 remote: Total 11 (delta 0), reused 11 (delta 0)
 Unpacking objects: 100% (11/11), done.
 Checking connectivity... done.

删除submodule

工作区:rm -rf B

暂存区:git rm --cache B

commit ,push到远程区

Git subtree

git subtree 可以实现一个仓库作为其他仓库的子仓库。 subtree的核心思想与能做的就只有同步项目文件。

假如有P1 、P2两个项目,两个项目存在共用的代码,将共用的代码独立为新的git仓库——share项目。

当你对P1/P2项目操作git clone或者git pull的时候,你拉取到的是整个P1/P2项目,包括share在内,share对于父级的主项目来说相当于是个普通目录;

当你在P1/P2项目修改了share里的内容后执行git push,修改的share文件将像其他普通文件那样push到P1/P2项目上。

subtree本质就是把子项目目录作为一个普通的文件目录,对于父级的主项目来说是完全透明的,真的就是个普通目录,原来是怎么操作现在依旧是那么操作,就像操作主项目中其他文件一样的 add commit。

确保各个项目已经添加这个 remote

 git remote add  <S项目别名>  <S项目远程库仓库地址>

关联subtree(只需要执行关联操作git subtree add即可,无需对share项目执行git clone)

  git subtree add --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <分支> --squash

--prefix之后的=等号也可以用空格

--squash意思是把subtree的改动合并成一次commit,这样就不用拉取子项目完整的历史记录。如果不加 --squash 参数,主项目会合并子项目本身所有的 commit 历史记录,加上 --squash 参数是把子项目的记录合成一次 commit 提交到主项目,这样主项目只是合并一次 commit 记录。

提交更改到子项目

 // git subtree push --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <S项目分支>
 git subtree push --prefix=src/share share master

高阶:每次push命令都会遍历全部的commit,当你的项目越来越大,commit的数上来的时候,等待时间就会很长。--rejoin 避免了遍历全部commit的问题.

 //git subtree split --rejoin --prefix=<S项目的相对路径> --branch <临时branch>
 git subtree split --rejoin --prefix=src/share --branch srcTemp
 //git push <S项目远程库仓库地址 | S项目远程库别名> srcTemp:master
 git push share srcTemp:master

更新子目录:

// git subtree pull --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <分支> --squash
git subtree pull --prefix=src/share share master --squash

git subtree 要不要使用 –squash 参数

使用 --squash 参数

  • 就是把 subtree 子项目的更新记录进行合并,再合并到主项目中:subtree add 或者 pull 操作的结果对应两个 commit, 一个是 squash 了子项目的历史记录, 一个是 Merge 到主项目中。

优点:主项目的历史记录看起来还是比较整齐的。 缺点:在子项目需要 subtree pull 的时候,经常需要处理冲突,甚至每次 subtree pull 的时候都需要重复处理同样的冲突。 原因:subtree add/pull 操作中,需要用到 merge,而 merge 顺利进行的前提, 是要有相同的 parent commit。原子项目历史记录被合并后就消失了,相当于一个“新”的提交。 下次再进行 add/pull 时,新添加的内容找不到“上一次的修改”, 于是在更新 subtree 内文件的时候,就会提示冲突,需要手工解决。

不使用 --squash 参数

优点:子项目更新的时候,subtree pull 很顺利, 能够自动处理已解决过的冲突。 原因: 原子项目的历史复制到了父项目中, 下次再进行 add/pull 时,新增的 commit 能够找到“上一次的修改”, 那么他会像在子项目中逐个 am patch 那样更新 subtree 下的内容, 不会提示冲突。 缺点:子项目的更新记录“污染”了主项目的。

总结

是否使用 squash 都是可以的, 但需要在开始阶段作出选择,并 一直坚持下去 。 如果一会儿用一会儿不用,得到的不是两者的优点,而是两者的缺点之和。

 

转移分支

在需要转移到的分支,cheery-pick 其他分支的commit版本号.一次只能复制一个commit

cheery-pick:将已提交的commit转移到其他分支,该操作属于复制操作,还产生新的版本号.但是原分支的没有被删除所以需要回到原分支删除commit.一般是checkout旧节点,然后删除分支 git branch -D,看需要是不是得把删除的分支补回来.

rebase(变基)

改变分支的根基,编写代码的地方.

一般建议不用

git

标签:有一个   邮箱   注释   原来   stash   git clone   点击   注意   核心   

原文地址:https://www.cnblogs.com/awsljava/p/11221178.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!