玩转Git三剑客
- 第一章:Git基础
- 0.怎么看git xxxx --help
- 1.基本配置
- 2.Git 基本命令
- 2.1建 Git 仓库
- 2.2往仓库⾥添加⽂件
- 2.2git的重命名
- 2.3git reset
- 2.4git diff
- 2.5git stash
- 2.6patch
- 2.7git checkout
- 2.8gitignore
- 2.9git alias
- 2.10git reflog
- 2.11git clean
- 2.12git clone
- 2.13git branch
- 2.14git log
- 12.14.1git show
- 2.12git rebase
- 2.13备份仓库
- 2.14git cherry pick
- 2.15git difftool
- 2.16git prune
- 将已有的项目添加到远端
- 2.17git revert
- 2.100git submodule
- 2.101 git hook
- 2.102 git checkout vs git reset
- 3.Git 探秘
- 第三章:Git与GitHub简单同步
- 第四章:Git多人单分支集成协作时的常见场景
- 第五章:Git集成使用禁忌 (2讲)
- 其它
课程: 玩转Git三剑客.
课件: 课件pdf.
Git官方参考文档: Git Book.
Git官方本地文档:file:///D:/Program%20Files/Git/mingw64/share/doc/git-doc/(如file:///D:/Program%20Files/Git/mingw64/share/doc/git-doc/git-clone.html)
第一章:Git基础
0.怎么看git xxxx --help
如git clone --help
git clone [--template=<template_directory>]
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
[-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
[--dissociate] [--separate-git-dir <git dir>]
[--depth <depth>] [--[no-]single-branch] [--no-tags]
[--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
[--jobs <n>] [--] <repository> [<directory>]
[]代表可选
<>代表必需
上例中,最简单的命令为:git clone repository,如git clone git@gitlab.bbbb:pjgggg/pjgggg-client.git,
如果要加可选的,如[ – depth < depth >],则加了–depth,则要加他的参数深度,如git clone --depth 1 git@gitlab.bbbb:pjgggg/pjgggg-client.git,表示只克隆深度为一层。
1.基本配置
$ git --version
git version 2.19.0
$ git config --global user.name ‘your_name’
$ git config --global user.email ‘your_email@domain.com’
config 的三个作⽤域,缺省等同于 local
$ git config --local
$ git config --global
$ git config --system
local只对仓库有效
global对登录⽤户所有仓库有效
system对系统的所有⽤户有效
显示 config 的配置,加 --list
$ git config --list --local
$ git config --list --global
$ git config --list --system
清除,–unset
$ git config --unset --local user.name
$ git config --unset --global user.name
$ git config --unset --system user.name
优先级
local > global > system
几个常用的设置
git config --global merge.ours.driver true
git config --global merge.ff no
git config --global pull.rebase true
git config --global rebase.autostash true
1.2
1.2.1 检查 ssh是否能正常连上gitlab
ssh
ssh git@gitlab.bbbb
如果密钥对设置好了,会有类似这样的提示
PTY allocation request failed on channel 0
Welcome to GitLab, @zhangjiequan!
Connection to gitlab.bbbb closed.
Win10下会提示,有水友提出各种解决办法,可以一试。
Bad owner or permissions on C:\\Users\\zhangjiequan/.ssh/config
1.2.2 权限太开放的问题
权限太开放问题
类似以下提示:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/Users/baioo/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/baioo/.ssh/id_rsa": bad permissions
用ls -l查看,发现id_rsa的权限不对
ls -l
-rw-r--r-- 1 baioo staff 1675 3 25 14:20 id_rsa
-rw-r--r-- 1 baioo staff 398 3 25 14:20 id_rsa.pub
-rw-r--r-- 1 baioo staff 369 3 25 14:20 known_hosts
drwxr-xr-x 5 baioo staff 160 3 25 12:06 leipeng
drwxr-xr-x 5 baioo staff 160 3 25 14:20 qiweiqi
drwxr-xr-x 8 baioo staff 256 3 25 14:22 zhangjiequan
改成,600,即只有所有者有读和写的权限
chmod 600 id_rsa
再检查权限,发现正常了,也可以通过ssh的使用条件验证了
-rw------- 1 baioo staff 1679 3 2 2018 id_rsa
-rwxr-xr-x 1 baioo staff 403 3 2 2018 id_rsa.pub
-rw-r--r-- 1 baioo staff 182 3 25 13:01 known_hosts
drwxr-xr-x 5 baioo staff 160 3 25 12:06 leipeng
drwxr-xr-x 5 baioo staff 160 3 25 14:20 qiweiqi
drwxr-xr-x 8 baioo staff 256 3 25 14:22 zhangjiequan
1.2.3 查看ssh的日志
ssh -vvvT git@gitlab.bbbb
GIT_TRACE=1 GIT_SSH_COMMAND=“ssh -vvv” git clone git@gitlab.bbbb:zhangjiequan/refreshporjects.git
2.Git 基本命令
2.1建 Git 仓库
两种⽅式:
- ⽤ Git 之前已经有项⽬代码
$ cd 项⽬代码所在的⽂件夹
$ git init
- ⽤ Git 之前还没有项⽬代码
$ cd 某个⽂件夹
$ git init your_project #会在当前路径下创建和项⽬名称同名的⽂件夹
$ cd your_project
2.2往仓库⾥添加⽂件
$ git add .
$ git commit -m "test add all"
$ git commit -am "add 和 commit 二合一"
$ git commit --amend #改最近一次提交的msg,amend修正
$ git commit --allow-empty -m "empty commit" 空提交
2.2git的重命名
git mv
$ git mv file_from file_to #将file_from重命名为file_to,并加入暂存区
#以上一条操作,等于以下组操作
#组1
$ mv file_from file_to
$ git add file_to
$ git rm file_from
#组2
$ mv file_from file_to
$ git add .
#组3
$ mv file_from file_to
$ git add file_to
$ git add file_from
注意,组1和组3中,分别对file_from进行git rm和git add,效果是一样的.所以,怎么理解git rm??git rm
2.3git reset
git reset --hard #什么都不管,直接还原到指定commit,不写则还原到HEAD
git reset --soft #??soft和mix的区别
git reset --mix #??soft和mix的区别
git reset --hard HEAD~1 #指定commit,为Head的前一个commit
git reset --hard commitId#指定commitId
git reset <file> #暂存区的东东unstaged到工作区<指定文件> ,默认是mix
2.4git diff
git diff #工作区与暂存区的差别
git diff --cached #暂存区与HEAD的差别
git diff HEAD #工作区和HEAD的差别
git diff --cached --raw #"以原始格式生成差异",个人理解是“一行信息版”
git diff --cached --compact-summary #简要版
git diff commitId1 commitId2 #对比两个commiId/branchName,commitId2比commitId1多/少了什么
git diff commitId1 commitId2 -- file #指定文件的差异【vs code对比指定文件没反应?PowerShell/Cmder可以正常diff】
2.5git stash
$ git stash #默认信息
$ git stash save message_to_type #自定义信息
$ git stash list #列出来
$ git stash pop 1 #弹出并应用第1个
$ git stash apply 1 #应用第1个
$ git stash drop 0 #删除第0个,也可以写成git stash drop stash@{0}
2.6patch
Git 打补丁-- patch 和 diff 的使用(详细)
2.6.1diff
用git diff生成的UNIX标准补丁.diff文件, .diff文件只是记录文件改变的内容,不带有commit记录信息,多个commit可以合并成一个diff文件。
$ #git diff 【commit sha1 id】 【commit sha1 id】 > 【diff文件名】
$ git diff 2a2fb453992 89aebfcc > patch.diff
2.6.2format-patch
用git format-patch生成的Git专用.patch 文件,.patch文件带有记录文件改变的内容,也带有commit记录信息,每个commit对应一个patch文件。
$ #*某次提交(含)之前的几次提交:
$ #git format-patch 【commit sha1 id】-n
$ git format-patch 2a2fb4539925bfa4a141fe492d9828d030f7c8a8 -2
$ #*某个提交的patch:
$ #git format-patch 【commit sha1 id】 -1
$ git format-patch 2a2fb4539925bfa4a141fe492d9828d030f7c8a8 -1
$ #*某两次提交之间的所有patch:
$ #git format-patch 【commit sha1 id】..【commit sha1 id】
$ git format-patch 2a2fb4539..89aebfcc7
2.6.3应用diff/patch
检查patch/diff是否能正常打入:
git apply --check 【path/to/xxx.patch】
git apply --check 【path/to/xxx.diff】
打入patch/diff:
git apply 【path/to/xxx.patch】
git apply 【path/to/xxx.diff】
2.7git checkout
git branch -av
#1、新建本地分支release/hotfix-1
#2、release/hotfix-1分支跟踪origin(远端)的release/hotfix-1
#3切换到本地分支release/hotfix-1
git checkout -b release/hotfix-1 origin/release/hotfix-1
#git push <REMOTENAME> <BRANCHNAME>
git push origin release/hotfix-1 #简写为git push
git checkout . #丢弃工作区所有的文件,使之和暂存区一样
git cehckout file #丢弃指定文件,使之和暂存区一样
创建并切换
创建并切换到iss53这个分支:
$ git checkout -b iss53
上面一条命令是下面两条命令的简写:
$ git branch iss53#创建
$ git checkout iss53#切换
2.8gitignore
github提供的各种流程框架的 ignore参考.
.gitignore书写格式是 glob,很多编程语言和配置都会使用 glob 来模糊匹配文件名和文件夹。
一个git工程的可以有多个.gitignore文件,分别管自己的文件夹。
2.9git alias
git config --global alias.st status
[alias]
st = status
co = checkout
ci = commit
br = branch
unstage = reset HEAD
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
rsh = reset --hard
2.10git reflog
“危险”操作的后悔药
2.11git clean
git clean -fdx #删除得干干净净,慎用!!
-d 删除未跟踪的目录和未跟踪的文件。如果一个未跟踪的目录是另一个不同的 Git 库,默认 将不会把它删除。如果你想删除这个目录,可以使用 -f
-f , --force 如果 Git 配置中 clean.requireForce 没有设置为 false,git clean 将拒绝执行。除 非是使用 -f -n -i
-n , --dry-run 仅仅显示将被删除的文件,不会真正的删除。强烈建议clean前,加入,先看一下要删除什么,如git clean -nd
-x 不使用 .gitignore(每个目录)和 $GIT_DIR/info/exclude 的标准忽略规则,但仍然使用使用 -e 选项给出的忽略规则。这允许删除所有未跟踪的文件,包括构建产品。 这可以使用(可能与 git reset)以创建一个原始的工作目录来测试一个干净的构建
-X 只删除 Git 忽略的文件。这可能有助于从头重建一切,但保留手动创建的文件
2.12git clone
$ git clone --depth=1 https://github.com/bcit-ci/CodeIgniter.git #--depth=1 表示只下载最近一次的版本,使用浅复制可以大大减少下载的数据量
$ git fetch --unshallow#如果之后又想获取完整历史信息,可以这样fetch
2.13git branch
git branch -av #all & verbose[所有(远端和本地)&冗长的(Commit id前缀)]
git branch -d dev2 #删除分支
git branch -D dev2 #删除分支
2.14git log
git log -n2 #查看最近两次修改
git log Assets\AtlasSource\imagetext\skinlib\widget_cardgame\kapai_lan.png #查看某个文件的log
git-log
–full-history 包括merge的信息
git log --full-history .\gitTest\somethingInMaster.md
找包含Merge信息的提交
git log --all --grep=‘Merge’
12.14.1git show
git show都是基于commit hashID输出的。
1.查看最新的commit
git show
2.查看指定commit hashID的所有修改:
git show commitId
3.查看某次commit中具体某个文件的修改:
git show commitId fileName
2.3 Git 基础 - 查看提交历史
–stat 显示每次提交的文件修改统计信息。
git show --stat commitId >3d973889.txt
2.12git rebase
#改某个已commit的msg reword
git rebase -i d61e7b3 #从commit id开始变基交互式;r(reword),保存;改commit msg,保存.观察新的log,d61e7b3之后的commit id都不同的。具体如下:
#pick d61e7b3 addmaster2 ##这和条是没有的,因为是从d61e7b3开始变基
#pick c78b010 addmaster3 ##把这条的pick改成r,保存,关闭,然后改commit msg,保存,关闭,完成。即c78b010这条msg改好了。
#pick e457ca4 addmaster4
#多个连续commmit合并成一个commit
git rebase -i 8ed0783 #s(squash),压缩多个commit,把当前的commit向前合具体如下:
#pick d61e7b3 addmaster2 ##这和条是没有的,因为是从d61e7b3开始变基
#pick c78b010 addmaster3 ##这条不能改成s,因为它没有前一条
#pick e457ca4 addmaster4 ##把这条的pick改成s,保存,关闭,然后改commit msg,如addmaster3改成addmaster3 +4,保存,关闭,完成。即e457ca4 这条commit会合到前一条commit(c78b010)上。
git rebase -i 8ed0783 #s(squash),压缩多个commit,把当前的commit向前合,调整git-rebase-todo文件中commit id的顺序,使用git rebase --continue。具体类似上面的“多个连续commmit合并成一个commit”
2.12.1 merge vs rebase
Git merge和rebase分支合并命令的区别
有两本地分支,master和feature
merge:
#将分支切换到 master:
git checkout master
#将分支 feature 合并到当前分支(即 master 分支):
git merge feature
rebase
1、和 git merge 不同的是,你需要在 feature 分支上进行 git rebase master 的操作,意味着让当前分支 feature 相对于 分支 master 进行变基
2、我们遇到了冲突,进行对比的双方分别是 master 分支的最新内容和 feature 分支的第一次提交的内容,上图下方红框内容告诉我们,在我们解决了冲突之后,需要执行 git rebase --continue 来继续变基的操作。(用git add来标记解决冲突)
3、解决完冲突,会发现成了一条线。feature的base成了master的head,feature的commits在这个head之后。
4、回到master,将 feature 分支合并进来(用git merge feature),此时,master可以faster-forword了,所以master是一条线。
5、如果想把feature的几个提交合成一个提交,可以用git rebase -i 8ed0783 #s(squash)
#将分支切换到 feature:
git checkout feature
#将当前分支(即 feature 分支)变基成 master(变当前分支的基,把基成master的head):
git rebase master
# 如果有冲突,则:解决冲突,add ,rebase --continue
# git add
# git rebase --continue
# 冲突解决完了,则完成
git merge,同一个冲突解决过了,再合并,会再冲突吗?
不会,因为合并的是“变更”,而不是“文件”。所谓的变更,就是加了一行,减了一行这种。而“文件”,即对比文件覆盖。因为这个变更已经合过了,就不会再有了。
2.13备份仓库
哑协议与智能协议
直观区别:哑协议传输进度不可⻅;智能协议传输可⻅。
传输速度:智能协议⽐哑协议传输速度快。
$ git clone D:\zjq\other-rep\learngit yaxieyi #哑协议
$ git clone file://D:\zjq\other-rep\learngit zhinengxieyi #file智能协议
$ git clone --bare file://D:\zjq\other-rep\learngit #--bare clone裸仓库,只有.git下的文件
$ git remote -v #查看远端
$ git remote add my_origin_name file://D:\zjq\other-rep\learngit #加远端
$ git push my_origin_name #push到指定远端,有默认值,origin, 这个默认值是通过“跟踪”完成的?
添加远端的实例
git remote add origin-out ssh://git@119.34.4.123:9200/family/bookvaccine.git
git会在本地仓库的.git文件夹下的config中添加一个remote的配置项。
更新远程分支列表
git remote update origin --prune
更新远程tag列表
git fetch origin #fetch 做的事情有点多
git tag -l | xargs git tag -d #删除所有本地分支
git fetch origin --prune #从远程拉取所有信息
git checkout 1.4 #切到指定tag
2.14git cherry pick
git cherry-pick <commit>
廖雪峰-解决冲突:
git add readme.txt 标记解决
git解决二进制文件冲突:
git checkout FILE --ours [ --theirs ]
Git操作 :从一个分支cherry-pick多个commit到其他分支
2.15git difftool
$ git difftool
2.16git prune
?
git gui
this repository currently has approximately loose 20000 objects
$ git prune # prune 修剪;删除;剪去;删除;减少 ?
将已有的项目添加到远端
git init
git add .
git commit -m ‘提交说明’
git remote add origin git@gitlab.bbbb:zhangjiequan/learn-unity.git #remote add origin 远程仓库地址
git push -u origin master
2.17git revert
git commitId1
# 回滚commitId1
git commitId3 commitId2 commitId1
# 依次回滚commitId3、commitId2、commitId1.所以,这里commitId3在commitId2之后提交的,123可以是分散的3个提交。即git revert NEWER_COMMIT OLDER_COMMIT
git commitId3^..commitId1
# 依次回滚commitId1、commitId2、commitId3,这里commitId3在commitId2之后提交的,123是连续的, 即git revert OLDER_COMMIT^..NEWER_COMMIT。如果是new^..old,则报错“error: empty commit set passed”,应该是没有这个集合,因为用new往后找,找不到old
git revert -n OLDER_COMMIT^..NEWER_COMMIT
# 合成一个提交
2.100git submodule
2.101 git hook
2.101.1 hook在mac上不生效的问题
hint: The ‘.git/hooks/pre-auto-gc’ hook was ignored because it’s not set as executable.
hint: You can disable this warning with git config advice.ignoredHook false
.
设置成executable?
是的,默认是不可执行的。
chmod 777 <file>
参考:
Linux权限管理使用总结
2.102 git checkout vs git reset
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改(即使用暂存区覆盖工作区)时,用命令git checkout – file。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了场景1,第二步按场景1操作。
# 把暂存区的内容放回工作区,包括修改、删除、增加文件。
git reset head
# 使用暂存区覆盖工作区
# 工作区改了文件、删了文件,都能用暂存区的去覆盖
# 不过,如果工作区增加了文件a/b.txt,则使用git checkout a,git checkout a/b.txt都无法删除工作区的文件
# 因为暂存区中无a/b.txt。即checkout不会对新增文件做删除
git checkout rsh-co.txt
3.Git 探秘
commit、tree、blob
HEAD、branch、Tag->commit
更多参见:高見龍 Git 連續劇
第三章:Git与GitHub简单同步
1.注册一个GitHub账号
2.配置公私钥
3.在GitHub上创建个人仓库
4.把本地仓库同步到GitHub
第四章:Git多人单分支集成协作时的常见场景
1.不同人修改了不同文件如何处理?
git clone git@gitlab.bbbb:pjgggg/pjgggg-client.git pjgggg-client_local_dic_name
git featch origin #简写为:git featch
git merge origin/release/hotfix-1#远端的hotfix合并到当前分支
#除了merge,也可以用rebase
2.不同人修改了同文件的不同区域如何处理?
#commit了,直接push会被拒绝,因为远端改了所以要:
git fetch # ahead 1,behind 1,即比远端“前了一个”,“又后了一个”
git merge orign/develop #将远端dev合到本地dev
或者直接git pull?
git pull等于git fetch + git merge?
git pull等于git fetch + git rebase?
用rebase的方式来pull
git pull --rebase
#或者详细写成以下,即加上origin远端名,develop分支名
git pull --rebase origin develop
3.不同人修改了同文件的同一区域如何处理?
4.同时变更了文件名和文件内容如何处理?
5.把同一文件改成了不同的文件名如何处理?
第五章:Git集成使用禁忌 (2讲)
1.禁止向集成分支执行push -f操作
push -f 强制push,直接覆盖远端。
github gitlab有相关机制禁止push -f。
2.禁止向集成分支执行变更历史的操作
向集成分支执行变更历史的操作,如rebase一下,改一下历史的commit msg。
如果执行了,其它的开发者会懵逼。
其它
1批量clone
使用Python 3通过gitlab的web api拿到json后逐一clone
git-game
git-game
git-game-v2
参考答案:
Git Game: Copying and Pasting From Documentation
Git Game v2: Copying and Pasting From Stack Overflow
来自华工计院16级的小师弟,写得比较详细,有趣(从标题能看出一二,哈哈)