git
杂
代理
1
2
3
4
5#只对github.com
git config --global http.https://github.com.proxy socks5://127.0.0.1:7890
#取消代理
git config --global --unset http.https://github.com.proxy使用 token:
https://<access token>@github.com/<userName>/<repository>.git
git in git
,也就是submoudle
会发生奇妙的事件其他版本控制系统大多是
delta-based
,但 git 是给每个文件保存一个快照,然后有一个索引指向(如果没有修改,就用以前的索引)git config --global init.defaultBranch main
.gitnore
Blank lines or lines starting with # are ignored.
Standard glob patterns work, and will be applied recursively throughout the entire working tree.
You can start patterns with a forward slash (/) to avoid recursivity.
You can end patterns with a forward slash (/) to specify a directory.
You can negate a pattern by starting it with an exclamation point (!).
git commit -a
自动 add tracked file 并且提交git rm
也会将文件从工作区内删除,git rm --cached
保留工作区重命名,最好用
git rm
普通的
git reset a
只是取消 staged,但并不会对工作区文件修改突然发现我之前解决的误区还在困扰着我,文件夹的实际大小并不包含文件,也就是说文件加其实包含的内容很少
除了文件目录的概念,有三个关键概念(存储在 objects 中)
blob:只是存储着文件实质二进制内容
tree:每次 commit,都会产生一个 tree,它的内容实际上就是所有该次提交需要指向的新的 blob 的 hash 值(以及对应的文件名,权限)
commit:tree 的 hash 值,parent tree 的 hash 值,author 相关信息,commitor 相关信息,message。此外还需要了解的是:
index:也就是存储着 staged 的 blob 的 hash 值(以及对应的文件名,权限)。即是由它组成了 tree 的一部分git 文件目录:
objects
存储着 blob,info(pack 的索引) 和 pack 存储着压缩的二进制信息。有取的是,其他文件夹是 hash 值得头两个字符,也是一个索引方式,里面存储着实际的 blob(content 信息,没有 meta data)。这么做的原因是如果说是有很多 blob 存储在一个文件夹中,那么去寻找是很慢的事情,所以通过进一步索引可以加快速度refs/heads
存储着分支信息,实际上每个分支名都有一个文件,文件的内容只是一个 commit 的 hash 值。index
存储着 staged 的 blob 的 hash 值(以及对应的文件名,权限)。即是由它的内容组成了 tree 的一部分。此外一个文件在 git 中的诞生,也是从加入 index 中开始(因为在此创建了 blob)HEAD
分支名(以 ref 起头来标志)或者是 commit hash 值。git status
实质就是比较 working direcotry 和 index 和 HEAD 指向的 commitgit merge
几种方式git branch -f <branch_name> <commit_name>
强制改变分支指向
git 服务器
- 本地协议:克隆本地仓库:
git clone /srv/git/project.git
,在共享文件系统有用。http 协议,ssh 协议,git 协议.. - 简单搭建 server
- 复杂搭建可以用
gitlab
命令
1. basics
- ssh -T git@github.com //-T 就是不分配伪终端,只显示连接信息
测试能否连接到 github
确定已经有添加 ssh 密钥,确定 config 文件配置正确,确定能 ping 通 github.com - git init
- git add (.)
- git commit -m ‘’
- git status
- git rm
- git cherry-pick <commit> (复制一个特定的提交到当前分支)
- git blame filename 显示谁修改了文件
2. diff
- git diff 工作区与暂存区
– <filename> 指定文件(注意空格) - git diff HEAD 工作区与 commit
- git diff –chached(暂存区与commit)
即未使用参数,默认是工作区与 xx 比较
3. reset
- git reset <file> (将某文件从暂存区移除,不修改工作区,不加文件是所有)
- git reset –hard (移除暂存区修改,删除工作区修改)
- git reset <commit> (可以用 head^ 回滚到指定版本,清除暂存区,但保持工作区不变)
- git reset –hard <commit> (回滚到指定版本,清除暂存区,删除工作区修改)
git reflog 可以查看被删除的版本号
–mixed 是默认参数,保留工作区,修改暂存区,不会移动 head 指针
–hard 修改工作区和暂存区,会移动 head 指针,此时提交会丢失指定版本之后的内容
4. branch
- git branch 显示分支
git branch <branchname>
创建分支
-d 删除
-m 改名
-f 后跟两个分支,让前者强制指向一个提交(如果同游,那么用 rebase 也可以)
-u <name1> (<name2>)
让 当前分支(name2
) 跟踪name1
- git checkout <branchname> 切换分支
-b <name1> (<name2>)
新建并切换到 name1,设立对远程分支 name2 的跟踪 git merge <branchname>
采用 Fast Forward 合并分支(此模式不会显示合并信息)
–no-ff 不使用 Fast Forward 模式,会显示合并信息,会产生新的 commit 所以同时需要 -m 参数- git switch 作用同 checkout
git cherry pick <commit>
复制一个特定的提交到当前的分支(指复制相同的改动操作)git rebase <commit>
变基,合并两个分支成一条线(直到公共祖先)
以当前位置为最新的提交(即当前位置动)
或者指定两个提交,以第一个提交为最新的提交(即前者不动,后者动)
会自动将 head 指向最后一个参数- git branch –set-upstream-to <branch-name> origin/<branch-name> 关联上游分支,不用记,会有提示
5. remote
- git remote -v 查看远端仓库信息
git remote add <name> <url>
(eg:git@github.com:llleixx/helloworld.git)git remote rm <name>
删除远程仓库的绑定- git pull
git push <remotename> <commit>(:<branchname>)
将某个提交推送到远端某个分支
-u 关联远程分支
-f 强制
git push origin :foo
传递空的本地分支可以用于删除远程的分支git fetch
<remotename> <commit>(:<branchname>)
将远程的某个提交下载到本地并且将一个分支指向它(这里的分支是本地的,而且如果不存在会自动创建,普通的 fetch 只是远程的指向,因为还没有 merge)git push origin --delete branchname
删除远端分支- git clone <name> (eg:git@github.com:llleixx/helloworld.git)
6. log
git log -<limit>
-p
详细信息- git log – <file>
- git log –graph
- git relog (命令历史)
7. stash
- git stash 储存工作区和暂存区(切换分支会丢失工作区和暂存区信息)
sava “message” 同时储存注释信息 - git stash list 查看
- git stash apply (<stashname>) 恢复但不删除stash,默认最新
- git stash drop (<stashname>) 删除stash
- git stash pop (<stashname>) 恢复并删除
8. tag
- git tag 查看所有标签
git tag <tagname>
给 HEAD 指向打 tag
-d 删除标签git tag <tagname> <commit>
- git tag -a <tagname> -m <annotation> <commit> 创有说明的标签
- git show <tagname> 显示说明
- git push origin <tagname> 推送某个标签
–tags 是推送所有标签
9. config
- git config –global –list
- git config –global user.name xx
- git config –global user.email “email@email.com ”
杂
HEAD表示当前分支最新提交版本,HEAD^上个版本,HEAD^^上上个版本,上100个版本可以写HEAD~100
git status 查看状态
1
2
3Untracked files 未跟踪(新创建,从未add过的文件)
Changes not staged for commit 未add
Changes to be committed add但未commit分支间相同文件进行不同修改会有冲突,此时merge失败
此时可以用 git status 告诉我们冲突文件
查看文件内容,Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容
修改(修改成你想要的样子,可以与所有分支都不同),add,commit。就能成功合并了(不用再merge,相当于merge失败→修改→add,commit→合并成功)origin/dev 像调用本地分支一样调用远程分支(其实两者没什么差别)
使用 https 协议,可以通过设置 credential helper 来只用第一次输入密码
git config –global credential.helper store //这是全局配置,执行后,会在用户目录下(这里没有指定位置)生成 .git_credential 里面存储着账号和密码使用 ssh(git) 协议更快,设置密钥后才能使用
git merge 和 git rebase
git merge master feature 将 master 合并到 feature 上
git merge 每次合并上游更改时 feature 分支都会引入一个外来的合并提交。如果 master 非常活跃的话,这或多或少会污染你的分支历史。
git rebase 它会把整个 feature 分支移动到 master 分支的后面,有效地把所有 master 分支上新的提交并入过来。但是,rebase 为原分支上每一个提交创建一个新的提交,重写了项目历史,并且不会带来合并提交。
不过,这种简单的提交历史会带来两个后果:安全性和可跟踪性。如果你违反了 rebase 黄金法则,重写项目历史可能会给你的协作工作流带来灾难性的影响。此外,rebase 不会有合并提交中附带的信息——你看不到 feature 分支中并入了上游的哪些更改。
综上,rebase 适用于开发 feature 分支时,master 分支已经被更新,需要再在新的 master 分支下开发,这时就可以用 rebase 将当前分支移动到 新的master 分支后
代码回滚
工作区:
git checkout -- a.txt
git checkout -- .
所有git checkout <commitID>(head) <filename>
暂存区:
git reset HEAD .
git reset HEAD a.txt
不加参数是采用了默认的 –mixed 参数只改变暂存区,所以如果想再还原工作区,需要用到1
本地分支
git log 得到提交id
git reset –hard HEAD^ 回到最新的一次提交
git reset –hard回到你想要的版本
git reset HEAD^ 此时代码保留,回到 git add 之前远程仓库
git log
git reset –hard
git push -f origin HEAD(或者当前分支名) 强制提交
or
git revert HEAD
git push origin master(不用 -f 了)git revert 和 git reset 区别
git revert 是指定一个提交,在当前分支的基础上新建一个提交(为指定提交的副本),常用于远程
git reset 是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除这两个命令都需要 HEAD 指向一个分支(不是直接指向提交,不然不知道操纵的哪个分支)
git commit –amend -m ‘sdfa’
相当于删除上次提交,换成当前这次
一般情况是 head 指向分支,分支指向一个具体提交,我们可以用
git checkout <commit name>
来分离 head 和分支^
上一个,~<num>
前多个。main^^
,即^
可以用于任意一个表示的合法分支(不能是提交 hash 值)^2
也可以有数字,这是用于一个结点有多个父亲时,用^2
代表第二个父亲git cherry-pick <commit name>
可以同时指定多个提交(这些提交甚至可以不是祖先关系,但可能有冲突),来将对应的提交创建一个副本到当前分支上(rebase 是指定一个提交,然后合并到公共祖先的整个路径,而且原来的会删除)交互式的 rebase:
git rebase -i HEAD~4
指定一个提交,可以调整当前提交到指定提交内的提交(不包括指定的提交),所以两者需要是祖先关系?作用:
- 调整提交记录的顺序
- 删除不想要的提交
- 合并提交
git commit --amend
修改最新的提交(不会产生新的提交)git describe (<commit>)
描述指定提交(或当前)的上游最近的 tag返回的组成是
<tag>_<numCommits>_g<hash>
,tag 名称,距离,和询问的提交 hash 值
远程
远程默认名称为 origin
默认不能动远程分支,切换到分支名自动会变成 HEAD 分离状态
也就是说
git checkout origin/main
会指向对应的提交,而不是 maingit fetch
从远程仓库下载本地仓库缺失的提交记录,更新远程分支指针。即同步远程仓库(他并不会改变你本地的仓库,这两者不同)。git pull
先抓取(fetch),后合并(merge)本地仓库(会在本子仓库产生一个新的提交),即是(git fetch, git merge)的缩写,注意合并是与当前指向的提交合并。git push
git push 前需要保证先与远程是同步的,才能 push 成功git pull --rebase
就是fetch, rebase
的缩写,也就是为了提交先满足同步远端时,可以用这个命令先同步从最最后的最上游开始 rebase 才能保证不丢失分支(分支在一条线上),因为 rebase 是建立副本,删除原来,分支信息不会跟着移动