clone git上的代码
1、安装git客户端
Windows:
git客户端:下载地址
TortoiseGit:下载地址
Linux:
git:yum -y install git git-core*
2、Git配置(使用自己的账号和邮箱)
git config --global user.name “XXX”
git config --global user.email “XXX.com”
3、某些仓库需要有权限才能提交MR,生成公钥
ssh-keygen -t rsa -C “XXX.com”
三个选项直接回车默认。
在linux下默认生成公钥的目录是/root/.ssh/id_rsa
在windows下则为C:\Users\.ssh
其中id_rsa.pub文件为ssh公钥,id_rsa为ssh私钥。
把id_rsa.pub公钥添加到git平台自己账号的个人配置中即可
GitHub更新已经fork的项目
1、clone 自己的 fork 分支到本地
可以直接使用 GitHub 客户端,clone 到本地,如果使用命令行,命令为:
$ git clone ssh:fork的项目.git
2、增加源项目的分支地址到我们fork项目的远程分支列表中
此处是关键,将源项目的仓库名指定为 upstream,命令为:
$ git remote add upstream ssh:源项目.git
注:$ git remote remove upstream 可以删除掉该远程分支
3、使用 git remote -v 查看远程分支列表
$ git remote -v
4、对齐远程分支上的origin/XXX新建本地XXX分支,并切换到这个分支上
$ git checkout -b XXX origin/XXX
5、fetch将fork项目上的源项目分支的新版本upstream拉到本地仓库(只是到仓库,不合并到本地工作区,没事可以多fetch,实时更新远程最新代码)
$ git fetch upstream
6、合并源项目分支版本的XXX分支代码到本地工作区(可能有冲突)
$ git merge upstream/XXX
7、将合并后的代码 push 到远端我们fork的项目中
$ git push origin XXX
fetch + merge 与 pull 的关系
git fetch是将远程主机的最新内容拉到本地仓库,用户之后可以决定是否merge到本机工作分支中,merge可能有冲突。
而git pull则是将远程主机的最新内容拉下来后直接merge,即:git pull = git fetch + git merge,这样也可能会产生冲突,需要手动解决。
简单的代码提交流程
1、git status 查看工作区代码相对于暂存区的差别
2、git add . 将当前目录下修改的所有代码从工作区添加到暂存区 . 代表当前目录
建议使用 git add 指定文件
或者
git add -i,可视化git界面,然后选2,即update,然后对需要git add的文件输入对应编号回车确认,最后回车退出
3、git commit -m “注释” 将缓存区内容添加到本地仓库
4、git push origin master 将本地版本库推送到远程服务器,
origin是远程主机,master表示是远程服务器上的master分支,分支名是可以修改的
git stash用法总结和注意点
基本使用
stash命令可用于临时保存和恢复修改(新添加的文件是不会stash进去的),可跨分支。
使用的操作push pop相当于入栈,出栈,stash@{0}是栈顶
注:必须是修改的内容,在未add之前才能执行stash!
-
git stash [[save [message]] or [push [文件] [-m message]]]
保存,save为可选项,message为本次保存的注释不再推荐使用git stash save,推荐使用git stash push,push可以带指定路径文件,只stash该文件。
而git stash save后面跟着路径是无效的,还是会将缓存区所有修改的文件全部stash -
git stash list
所有保存的记录列表 -
git stash pop [[stash@{num}] or [num]]
恢复,num是可选项,通过git stash list可查看具体值。只能恢复一次 -
git stash apply [[stash@{num}] or [num]]
恢复,num是可选项,通过git stash list可查看具体值。可回复多次 -
git stash drop [[stash@{num}] or [num]]
删除某个保存,num是可选项,通过git stash list可查看具体值 -
git stash clear
删除所有保存
git reset三种模式解析
假设当前git的状态是这样的,本地工作区有个A文件,已经add提交了B到缓存区,已经commit了C到本地仓库
工作区 | index | 本地仓库 | ||
---|---|---|---|---|
本地 | A | |||
已经add | B | B | ||
本次commit | C | C | C | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
Git reset --soft HEAD^
工作区 | index | 本地仓库 | ||
---|---|---|---|---|
本地 | A | |||
已经add | B | B | ||
本次commit | C | C | C | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
变成:
工作区 | index | 本地仓库 | ||
---|---|---|---|---|
本地 | A | |||
已经add | B | B | ||
已经add | C | C | ||
本次commit | D | D | D | HEAD=HEAD^0 |
Git reset --mixed HEAD^(不指定–减减的话,默认为这个)
工作区 | index | 本地仓库 | ||
---|---|---|---|---|
A | ||||
add | B | B | ||
本次commit | C | C | C | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
变成:
工作区 | index | 本地仓库 | ||
---|---|---|---|---|
本地 | A | |||
本地 | B | |||
本地 | C | |||
本次commit | D | D | D | HEAD=HEAD^0 |
Git reset --hard HEAD^
工作区 | index | 本地仓库 | ||
---|---|---|---|---|
本地 | A | |||
add | B | B | ||
本次commit | C | C | C | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
变成:
工作区 | index | 本地仓库 | ||
---|---|---|---|---|
本次committ | D | D | D | HEAD=HEAD^0 |
如果提交了一个commit,发现还有代码需要修改,再提交几次commit就会造成一个功能对应了多条commit的冗余,因此用git reset回退到最初修改的commit id前一个版本,再重新git add提交这个功能的最终版本代码来去除commit冗余是很常见的做法。
git checkout --和git reset HEAD
同时让a.txt存在在工作区、index、本地仓库:
工作区 | index/缓存区 | 本地仓库/版本库 | ||
---|---|---|---|---|
A a.txt值为 1111111 2222222 3333333 | ||||
add | B a.txt值为 1111111 2222222 | B a.txt值为 1111111 2222222 | ||
本次commit | C a.txt值为 1111111 | C a.txt值为 1111111 | C a.txt值为 1111111 | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
此时进行git checkout – a.txt:会让缓存区的a.txt覆盖工作区的a.txt
工作区 | index/缓存区 | 本地仓库/版本库 | ||
---|---|---|---|---|
add | B a.txt值为 1111111 2222222 | B a.txt值为 1111111 2222222 | ||
本次commit | C a.txt值为 1111111 | C a.txt值为 1111111 | C a.txt值为 1111111 | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
而后进行git reset HEAD a.txt,将HEAD版本库的a.txt覆盖缓存区的a.txt
工作区 | index/缓存区 | 本地仓库/版本库 | ||
---|---|---|---|---|
B a.txt值为 1111111 2222222 | ||||
本次commit | C a.txt值为 1111111 | C a.txt值为 1111111 | C a.txt值为 1111111 | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
此时进行git checkout – a.txt:仍然是让缓存区的a.txt覆盖工作区的a.txt,所以得到:
工作区 | index/缓存区 | 本地仓库/版本库 | ||
---|---|---|---|---|
本次commit | C a.txt值为 1111111 | C a.txt值为 1111111 | C a.txt值为 1111111 | HEAD=HEAD^0 |
上次commit | D | D | D | HEAD^=HEAD^1=HEAD~1 |
HEAD^和HEAD~
commit会使得HEAD指向一个新的分支
HEAD是指当前的快照,这个命令主要配合reset的–hard,–mixed和–solf三个参数等操作对本次的修改进行处理
1、"^"代表父提交,当一个提交有多个父提交时,可以通过在"^"后面跟上一个数字,表示第几个父提交,"^"相当于"^1"。
2、~n相当于连续的n个"^1","~"相当于"~1"。
A = A^0
B = A^ = A^1 = A~1
C = A^2 = A^2
D = A^^ = A^1^1 = A~2
E = B^2 = A^^2
F = B^3 = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2 = B^^2 = A^^^2 = A~2^2
I = F^ = B^3^ = A^^3^
J = F^2 = B^3^2 = A^^3^2
1、G-D-B-A可以认为是主干,其他都是merge进来的其他分支节点。
2、A^表示A的第一个父提交(爸爸),A^2表示A的第二个父提交(妈妈)
3、A~1表示A的父提交,A~2表示A的父提交的父提交(爷爷),相当于A^^和A^1^1
4、A~2^2表示A的父提交的父提交的第二个父提交,即为H
创建删除本地/远程分支
git新建本地分支:
git branch 本地分支名(缺省默认在Head也就是当前位置创建分支)
git branch 本地分支名 加位置(如HEAD^^2或者commit号),则会在对应位置创建一个分支
checkout -b新建并切换到对应分支
如果远程分支存在:
git checkout -b 本地分支名 origin/远程分支名
如果远程分支不存在
git checkout -b 本地分支名
删除本地分支
使用命令git branch -d Chapater8
git新建远程分支:
git checkout -b 本地分支名
git push origin 本地分支名:新的远程分支名
git删除远程分支:
1、使用 git branch -a命令来查看所有的分支。
其中上方的是本地的分支,下方的有remotes/origin开头的就是远程分支。
2、假设要删除new_a的远程分支,我们需要先把分支切换到master,因为如果你现在所在的分支就是new_a,在这个分支下,是不能删除它的。
使用命令 git checkout master
3、删除远程分支的命令
git push origin --delete new_a
或
git push origin :new_a
推送一个空分支上去,相当于删除
4、git branch -a来查看现在所有的分支,会看到new_a分支已经没有了,被删除了。
git rebase
-
git rebase -i HEAD~4
到某个分支,会显示从HEAD到这个分支之间所有分支,可以删除掉某些分支或对这中间的分支重新排序,可以用于调试BUG的时候增加打印信息,然后提交的时候忽略这些打印信息的分支 -
git rebase C1 C2
等效于git checkout C2; git rebase C1,会将C1 C2的公共父节点C3到C2之间的所有提交记录都合入到C1中,不会产生新的commit。但是注意该动作会切换分支。
这命令会把C3到C2之间的每个提交(commit)取消掉,并且把它们临时保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把C2分支更新为最新的C1分支,最后把保存的这些补丁应用到C2分支上。 -
git cherry-pick C1 C2 C3
从当前分支合入C1,C2,C3三个分支的修改 -
git branch C1 C2
在C2位置上创建分支C1,如果C1分支已在别的位置存在,则由于分支名不能相等所以创建失败,可以强制创建,需要git branch -f C1 C2,强制将C1分支切换到C2上,也可以理解为删除原分支C1,在C2上创建一个新分支C1。
git branch动作不会切换分支,也不会动到HEAD,工作区和缓存区。