标签:有一个 邮箱 注释 原来 stash git clone 点击 注意 核心
git init
命令把这个目录变成Git可以管理的仓库,在该目录下就会多出.git目录
使用ls -ah就可以看见
默认是master分支
git commit
命令,-m
后面输入的是本次提交的说明
执行成功后:
1 file changed
:1个文件被改动(我们新添加的readme.txt文件);2 insertions
:插入了两行内容(readme.txt有两行内容)。
合并commit add
git commit -am "注释"
git log
命令显示从最近到最远的提交日志
可以加上--pretty=oneline
$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file
git reflog 看回退日志的
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 commit
或git 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分支 master 修改某个文件并提交后,master分支的版本就要相对与g1分支要早一步,然后切换到g1分支.g1分支下修改同一文件的同一位置,然后提交,然后合并分支时,就会产生冲突.
相对于svn,git不会产生多于的文件.
然后就用vim修复就可以了!
每次提交后的所有文件就是一次快照.
如果还没将某一个功能开发完毕,就要切换分支:建议1.保存现场(临时保存,stash) 2.切换
保存现场:git stash
还原现场:git stash pop(将原来保存的内容删除,用于还原现场)
git stash apply (还原内容,不删除原来的内容)
查看现场:git stash list
代表该项目的一些问题或者 bug,并不是说 Issues 越少越好,Issues 被解决的越多说 明项目作者或者组织响应很积极,也说明该开源项目的作者很重视该项目.
大家在使用一些开源项目有问题的时候都可以提 Issue,可以通过点击右上角的 New Issue 来新建 Issue,需要添加一个标题与描述就可以了,这个操作很简单。
参与开源项目的方式:
点击某个项目右上角的 Fork 按钮,然后该项目就出现在了你自己账号的 Repository 里。
可以看到 Fork 过来的项目标题底部会显示一行小字:fork from xxxxx
项目代码跟原项目一模一样,对于原项目来说,相当于别人新建了一个分支而已。
第二步,把该项目 clone 到本地,然后修改的 bug 也好,想要新增的功能也好,总之把自己 做的代码改动开发完,保存好。
接着,把自己做的代码改动 push 到 你自己的 GitHub 上去。第三步,点击你 Fork 过来的项目主页的 Pull requests 页面,点击 New pull request 按钮,可以看到自己添加了些什么东西,然后点击中间的 Create pull request 按钮,至此我们就成功给该项目提交了一个 PR。然后就等着项目原作者 review 你的代码,并且决定会不会接受你的 PR,如果接受,那么恭喜你,你已经是该项目的贡献者之一了。
这个项目就是方便你把一些 Issues、Pull requests进行分类,反正我觉得该功能很鸡肋
在工作区内创建.gitignore文件,在文件内填写要忽略的文件名
文件夹表示:dir/
统配符表示:*.xxx x.*
dir/*/
dir/**/ :忽略任一级
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 代码
如果本地库落后于远程库的版本.建议先pull拉取合并再push,不然,你也push不了.
记住,如果你pull下来后解决了冲突一定要告诉git你解决了冲突 git add xxxxx
注意:add后会进行两次提交,1次是最终提交,1次是将对方分支的提交信息commit也拿来了.
pull=fecth+merge
要我理解,就是你搞个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 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 可以实现一个仓库作为其他仓库的子仓库。 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
使用 --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,看需要是不是得把删除的分支补回来.
改变分支的根基,编写代码的地方.
标签:有一个 邮箱 注释 原来 stash git clone 点击 注意 核心
原文地址:https://www.cnblogs.com/awsljava/p/11221178.html