git学习
git 常用命令
获得版本库
git init
git clone
版本管理
git add 将已修改的文件纳入到暂存区
git commit 将暂存区提交到版本库
git rm 删除版本库中的特定文件
git rm --cached 从缓存区删除,文件回到工作区修改的状态
git reset HEAD <file> to unstatged
查看信息
git help 帮助信息
git diff 比较差别
git log 提交日志
远程协作
git push 拉取到本地
git pull 将本地版本信息推送到远程
git 提交的id (commit id ) 是一个摘要值,这个摘要值实际上是sha1计算出来的
可以通过id 寻找到特定的提交
对于user.name,user.email 有三个地方可以配置
1,/etc/gitconfig (几乎不使用) 全局 git config --system
2,~/.gitconfig (很常用) 针对当前用户 git config --global
3,针对于特定目录的,.git/config文件中 git config --local
git commit --amend --reset-author
===========================================================================================
git 添加,删除,修改,日志
1,git rm file 将误提交的文件删除--->先删掉,再提交
先删掉完成两个操作:rm file ,git add 到缓存区
然后再 git commit
如果误删,文件还在暂存区,以下命令恢复
git reset HEAD file 将待删除的文件从缓存区恢复到工作区
git checkout -- file 将工作中的修改丢弃掉
如果误删,文件已经commit到版本区
直接调用系统的rm 命令删除,文件不会纳入到缓存区,需要git add
2, 重命名 git mv <file1> <file2>
3, git commit --amend -m,修改上一次的提交记录
4, git log -n 查看最近的几条提交消息 git log -3
git 查看帮助文档
git help config
git config --help
man git-config
=====================================================================
.gitignore与分支
vi .gitignore
支持通配符 *.pro 所有以 .pro 结尾的文件git都会忽略,
!test.pro ,加“!” 表示test.pro除外
/TODO # 仅仅忽略项目根目录下的TODO,但不包括 subdir/TODO
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略doc/notes.txt 但不包括doc/server/arch.txt
/*/*.txt # 所有子目录下的.txt,一层子目录
/**/*.txt # 两层子目录
mkdir subdir && cd subdir 创建并进入目录
分支
git branch 查看分支
git branch new_branch 新建分支
git checkout new_branch 切换分支
git checkout - #切换回原来的分支
版本回退
回退到上一版本
git reset --hard HEAD^
git reset --hard HEAD~1
git reset --hard commit_id 回退
返回到某一版本
git reflog 查看操作记录
git checkout --test.c # 作用:丢弃掉相对于暂存区中的最后一个添加的文件
内容所做的变更
git reset HEAD test.c # 将之前添加到暂存区(stage,index暂存区也叫缓存区)
的内容从暂存区移除到工作区
分支改名
git branch -m branch_name1 branch_name2
保存工作现场
git stash 将当期修改暂存
git stash save "..."
git stash list 将所有保存的状态列出来
将暂存恢复:
git stash pop 恢复之后自动删除stash记录
git stash apply //恢复之后需要手动删除 git stash drop stash@{0}
git stash apply stash@{0} 指定恢复
=================================================
标签与diff
当需要发布一个版本的时候,或具有里程碑意义的时候,可以打一个标签
git tag v1.0
git tag v1.1 -m "..." 创建tag的时候加注释
git tag 显示所有标签
git show v1.0 显示tag详细信息
默认下git push 不推送tag,使用如下命令进行推送:
git push origin v1.0
git push origin v2.0 v3.0 一次推送多个tag
git push origin --tags 将所有未推送的tag一次推送
git blame # Show what revision and author last modified each line of a file
git log --graph 图形化显示log
diff
1,工作区与缓存区(或索引区)文件之间的差别
git diff
2,工作区与特定提交的id的差别
git diff commit_id
git diff HEAD :比较的是最新的提交与工作区的差别
3,缓存区与特定版本库之间的差别
git diff --cached commit_id #若不加id,则与最新的提交比较
===================================================================
远程协作
push 推送
pull 拉取,同时执行合并merge
pull == fetch + merge
git remote add origin https://github.com//....(仓库地址) # origin 对远程仓库起的别名
git@github.com
git push -u origin master # -u 表示关联 将本地的master与远程的master关联,以后再次
提交的时候就不用再指定master,之间使用git push就
将本地的master推送到远程的master
https:传输不加密,下次推送的时候还需要验证账户密码
ssh :需要将公钥放在远程,以后再推送就不用再验证密码
git remote add origin git@github.com 需要本地的私钥和公钥
git remote show origin
cd .ssh
vi known_hosts
生产公钥私钥
which ssh-keygen
/usr/bin/ssh-keygen
ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/xiangtingshen/.ssh/id_rsa):
回车,在.ssh目录下生成id_rsa id_rsa.pub
~/.ssh$ ls
id_rsa id_rsa.pub known_hosts
在git服务器上setting-->deploy keys,将公钥放进去(记得勾选allow write access),再次执行git remote show origin
git remote show origin
* remote origin
Fetch URL: git@github.com:xiangtingshen/learnGit.git
Push URL: git@github.com:xiangtingshen/learnGit.git
HEAD branch: (unknown)
再git push -u origin master 代码就可以提交到服务器上了
git remote show 查看远程仓库的名称
git remote show origin 查看远程仓库的详细信息
1.Gitflow
2.基于Git分支开发模型
develop分支(频繁变化的一个分支)开发人员
test分支(供测试与产品人员使用的一个分支,变化不是特别频繁)
master分支(生产发布分支,变化非常不频发的一个分支)
bugfix(hotfix)分支(当生产系统出现的紧急的bug,用于紧急修复的分支)
git branch -a
git branch -av
【16】
gitk git自带的图形化界面
【17远程分支和别名】
别名:git config --global alias.br branch
git br 就可以查看分支
相当于修改了家目录下.gitconfig文件
[alias]
br = branch
git config --global alias.ui '!gitk'
通过 git ui 即可以打开gitk命令,查看图形化界面
-----------------------------------------------------
拉取远程分支
下面两条命令等价
git checkout -b develop origin/develop
git checkout --strack origin/develop
将本地分支首次推送到远程
git push -u origin
git push --set-upstream origin develop
删除本地分支
git branch -d develop
git push 命令完整写法 git push origin src:dest # src:本地分支名,dest远程分支名,一般我们都设为相等,所以可以简写为 git push
git pull 命令完整写法 git pull origin src:dest
git push origin 空格:develop # 将远程develop分支删除
git push origin --delete develop # 将远程develop分支删除
=========================================================================================================
【18】
HEAD标记:HEAD文件是一个指向你当前所在分支的引用的标识符,该文件内部并不包含SHA-1值,而是指向另外一个引用的指针
当执行git commit 命令时,git 会创建一个commit对象,并且将这个 commit 对象的parent指针设置为HEAD所指向的引用的SHA-1值
cat .git/HEAD
ref: refs/heads/master
我们对HEAD修改的操作,都会被记录在 git reflog 中,除非直接修改vi .git/HEA文件,不建议这么做
我们也可以通过底层命令来修改 HEAD
git symbolic-ref HEAD 读取HEAD值
git symbolic-ref HEAD refs/heads/develop 修改指向develop,切换到develop分支
===========================================================================================
【19】
删除远程tag:
git push origin [空格]:refs/tag/v6.0
或者:git push origin --delete tag v6.0
删除本地tag
git tag -d v6.0
创建标签:git tag -a v7.0 -m 'v7.0 released'
推送到远程:
简便写法:git push origin v7.0
完整写法:git push origin refs/tags/v7.0:refs/tags/v7.0
拉取tag:
git fetch origin tag v7.0
refspec:
在缺省情况下,refspec会被git remote add 命令所自动生产,GIT会获取远程ref/heads下的所有引用,并将它们写在本地的ref/remote/origin目录下。
所以,如果远程有一个master分支,你在本地可以通过一下几种方式来访问他们的历史记录:
1,
git rm
用法:git rm [<选项>] [--] <文件>...
-n, --dry-run 演习
-q, --quiet 不列出删除的文件
--cached 只从索引区删除
-f, --force 忽略文件更新状态检查
-r 允许递归删除
--ignore-unmatch 即使没有匹配,也以零状态退出
git mv 1.c 2.c 修改名字
-- 相当于下面三条命令:mv 1.c 2.c, git rm 1.c, git add 2.c
git remote rename origin origin2 修改远程仓库的名称
【21 git submodule】
git init --bare 创建裸库
--bare 参数的含义,使用 --bare 参数初始化的仓库,我们一般称之为裸仓库, 因为这样创建的仓库并不包含 工作区 , 也就是说,我们并不能在这个目录下执行我们一般使用的 Git 命令。使用
git init --bare <repo> 可以创建一个裸仓库,并且这个仓库是可以被正常 clone 和 push 更新的, 裸仓库不包含工作区,所以并不会存在在裸仓库上直接提交变更的情况。https://www.jianshu.com/p/9a4e8750aea6
submodule 子模块: 将一个git仓库引用到另外一个git仓库
仓库1 引用仓库2 ,仓库2更新的时候,仓库1通过命令可以更新
git submodule add 被引用的远程仓库的地址git2 新的文件夹名称mymodule(表示将远程的引用的仓库放在哪个位置)
根目录下会多出一个 .gitmodules文件
.git 下面会多出一个modules文件夹,包含子模块的所有git配置相关信息
当子模块更新了的时候:
方式1:git1仓库只需要进入mymodule文件夹执行 git pull 就可以拉取子模块
方式2:在跟目录下执行 git submodule foreach git pull 可以将当前项目依赖所有的子模块更新
git add . ;git commit
当submodule存在的时候,克隆clone该项目的时候发生一些变化:
当执行 git clone 之后,mymodule文件下并不会有内容,需要在根目录下手工去执行:git submodule init; git submodule update --recursive
或者用这条命令clone的时候,一次性将子模块拉取: git clone地址 文件夹 --recursive
删除submodule:
1,从缓存区git rm --cached mymodule/
2,再从工作区删除rm -rf mymodule
3,git add , git commit, git push
【22 git subtree】
git submodule 存在以上问题,删除、修改子工程代码不方便,所以在后续的git版本中引用了subtree,subtree可以实现所有submodule功能
在主工程中修改子工程代码,可以推送到远程,子工程可以拉取。
{
github上创建新工程
本地git init,git config --local user.name '',git config --local user.email ''; git add .;git commit;
本地仓库关联到远程仓库 git remote add origin 地址
提交到远程 git push --set-upstream origin master 、git push -u origin master
}
主工程:git remote add subtree-origin git@github.com:xiangtingshen/git_subtreeChild.git
git remote show: 出现下面两个远程库
origin
subtree-origin
添加:--prefix=subtree 将引用的仓库放在subtree文件夹下面,subtree-origin 指明从哪引用,master引用的分支,--squash可选参数(压缩引用的仓库的多条提交历史为一条,防止子仓库的提交记录污染主仓库的提交记录,但是这条命令使用的时候如果有时候使用有时候不适用可能会引起一些问题,所以要么全部使用这条命令,要么不使用)
1,git subtree add --prefix=subtree subtree-origin master --squash
git fetch subtree-origin master
Warning: Permanently added the RSA host key for IP address '13.250.177.223' to the list of known hosts.
warning: 没有共同的提交
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
展开对象中: 100% (3/3), 完成.
来自 github.com:xiangtingshen/git_subtreeChild
* branch master -> FETCH_HEAD
* [新分支] master -> subtree-origin/master
Added dir 'subtree'
2,然后可以看到主工程下多了一个subtree文件夹,里面是引用的仓库内容。
3,然后执行 git push 推送到远程,远程仓库也多一个subtree文件夹,里面就是子工程的文件(与submodule不一样,submodule里面是子工程的一个引用,指针)
4,在子工程中修改子工程内容,推送到远程
5,主工程拉取:git subtree pull --prefix=subtree subtree-origin master --squash
会产生以下两条记录,一条合并子仓库的提交历史生产commit,一条合并子仓库和主仓库
commit 9a7c779613115472434415575f035deaf77d2618 Merge: ebcc687 cf56fa8 Author: Date: Thu Feb 20 09:34:07 2020 +0800 Merge commit 'cf56fa8f11e4ae559bd163799742fd6cbdfded5f' commit cf56fa8f11e4ae559bd163799742fd6cbdfded5f Author: Date: Thu Feb 20 09:34:07 2020 +0800 Squashed 'subtree/' changes from 8725fa5..c4edab6 c4edab6 add new file git-subtree-dir: subtree git-subtree-split: c4edab694425b9d8922b99c768f239f969624b74
6,在主工程修改子工程内容之后,git push仅推送到远程主工程仓库,还需要执行git subtree push --prefix=subtree subtree-origin master 才将修改推送到子工程
【24 cherry-pick】
将一个分支的提交应用到另一个分支上,如下,将develop分支上的两个提交应用到master分支上
commit 008a6fc4dfe355a9b72852047d45bd93176c05fb (HEAD -> develop) Author: zhangsan <123456789.163.com> Date: Mon Feb 24 08:36:40 2020 +0800 3 commit a55c47596207084c023cdf75844b10221f86a13e Author: zhangsan <123456789.163.com> Date: Mon Feb 24 08:36:30 2020 +0800 2 commit 5f08b3f8a1ae18e9024c054f9d712d0e2656410f (master) Author: zhangsan <123456789.163.com> Date: Mon Feb 24 08:34:33 2020 +0800 1
首先切换到master分支,然后 执行 git cherry-pick a55c475
git cherry-pick a55c475 [master 4cd082a] 2 Date: Mon Feb 24 08:36:30 2020 +0800 1 file changed, 1 insertion(+)
git cherry-pick 008a6fc4dfe355a9b [master 998881c] 3 Date: Mon Feb 24 08:36:40 2020 +0800 1 file changed, 1 insertion(+)
git log commit 998881cec314fd6d227b2069efa69d880d158b2b (HEAD -> master) Author: zhangsan <123456789.163.com> Date: Mon Feb 24 08:36:40 2020 +0800 3 commit 4cd082abd8a755b1519f77275a804631aabacfac Author: zhangsan <123456789.163.com> Date: Mon Feb 24 08:36:30 2020 +0800 2 commit 5f08b3f8a1ae18e9024c054f9d712d0e2656410f Author: zhangsan <123456789.163.com> Date: Mon Feb 24 08:34:33 2020 +0800 1
查看日志发现git已经自动将develop的两个提交应用到master分支,若以上先pick 008a6fc4dfe355a9b,则会有冲突,需要解决冲突。
将develop分支两个提交删除,恢复到提交之前的状态
git checkout 5f08b3f8a1 注意:正在检出 '5f08b3f8a1'。 您正处于分离头指针状态。您可以查看、做试验性的修改及提交,并且您可以通过另外 的检出分支操作丢弃在这个状态下所做的任何提交。 如果您想要通过创建分支来保留在此状态下所做的提交,您可以通过在检出命令添加 参数 -b 来实现(现在或稍后)。例如: git checkout -b <新分支名> HEAD 目前位于 5f08b3f 1 xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git branch develop master * (头指针分离于 5f08b3f) xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git branch --D develop error: unknown option `D' 用法:git branch [<选项>] [-r | -a] [--merged | --no-merged] 或:git branch [<选项>] [-l] [-f] <分支名> [<起始点>] 或:git branch [<选项>] [-r] (-d | -D) <分支名>... 或:git branch [<选项>] (-m | -M) [<旧分支>] <新分支> 或:git branch [<选项>] (-c | -C) [<老分支>] <新分支> 或:git branch [<选项>] [-r | -a] [--points-at] 或:git branch [<选项>] [-r | -a] [--format] 通用选项 -v, --verbose 显示哈希值和主题,若参数出现两次则显示上游分支 -q, --quiet 不显示信息 -t, --track 设置跟踪模式(参见 git-pull(1)) -u, --set-upstream-to <上游> 改变上游信息 --unset-upstream 取消上游信息的设置 --color[=<何时>] 使用彩色输出 -r, --remotes 作用于远程跟踪分支 --contains <提交> 只打印包含该提交的分支 --no-contains <提交> 只打印不包含该提交的分支 --abbrev[=<n>] 用 <n> 位数字显示 SHA-1 哈希值 具体的 git-branch 动作: -a, --all 列出远程跟踪及本地分支 -d, --delete 删除完全合并的分支 -D 删除分支(即使没有合并) -m, --move 移动/重命名一个分支,以及它的引用日志 -M 移动/重命名一个分支,即使目标已存在 -c, --copy 拷贝一个分支和它的引用日志 -C 拷贝一个分支,即使目标已存在 --list 列出分支名 -l, --create-reflog 创建分支的引用日志 --edit-description 标记分支的描述 -f, --force 强制创建、移动/重命名、删除 --merged <提交> 只打印已经合并的分支 --no-merged <提交> 只打印尚未合并的分支 --column[=<风格>] 以列的方式显示分支 --sort <key> 排序的字段名 --points-at <对象> 只打印指向该对象的分支 -i, --ignore-case 排序和过滤属于大小写不敏感 --format <格式> 输出格式 xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git branch -D develop 已删除分支 develop(曾为 008a6fc)。 xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git branch master * (头指针分离于 5f08b3f) xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git checkout -b develop 切换到一个新分支 'develop' xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git branch * develop master xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ cat test.txt 11
【26 rebase 变基、衍合】
rebase 变基 :改变分支的根基
rebase的功能类似与merge,二者可以完成类似的工作,不过工作方式有着显著的差别:rebase会改变git的提交历史。
》》一般来说,执行rebase的分支都是自己本地的分支,,没有推送到远程版本库,否则会引起很多麻烦
》》不要对master分支执行rebase,rebase会改变git的提交历史,否则会引起很多麻烦
rebase过程也会出现冲突,解决冲突之后,用git add添加,然后执行
git rebase --continue
接下来git会继续应用余下的补丁
任何时候都可以通过如下命令终止rebase,分支会恢复到rebase开始之前的状态
git rebase --abort
首先checkout mywork 分支,然后执行git rebase origin
rebase和merge的区别:

xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git checkout develop 切换到分支 'develop' xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git rebase master 首先,回退分支以便在上面重放您的工作... 应用:d2 使用索引来重建一个(三方合并的)基础目录树... M test.txt 回落到基础版本上打补丁及进行三方合并... 自动合并 test.txt 冲突(内容):合并冲突于 test.txt error: 无法合并变更。 打补丁失败于 0001 d2 用 'git am --show-current-patch' 命令查看失败的补丁 手工解决所有冲突,执行 "git add/rm <冲突的文件>" 标记 冲突已解决,然后执行 "git rebase --continue"。您也可以执行 "git rebase --skip" 命令跳过这个提交。如果想要终止执行并回到 "git rebase" 执行之前的状态,执行 "git rebase --abort"。 xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ vi test.txt xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git am --show-current-patch commit b15d83d687a69ea9820ad9af0909ad5a4d8e1683 Author: zhangsan <123456789.163.com> Date: Tue Feb 25 09:02:22 2020 +0800 d2 diff --git a/test.txt b/test.txt index b4de394..8e9630b 100644 --- a/test.txt +++ b/test.txt @@ -1 +1,2 @@ 11 +d2 xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git add . xiangtingshen@ubuntu1804:~/MyWorkSpace/Demo/git-cherry-pick$ git rebase --continue 应用:d2 应用:d3 使用索引来重建一个(三方合并的)基础目录树... M test.txt 回落到基础版本上打补丁及进行三方合并... 自动合并 test.txt
rebase之后gitk,develop记录


浙公网安备 33010602011771号