GIT-note
git init
git add
git commit -m “asdasd”
git status
git diff
用git diff HEAD -- readme.txt
命令可以查看工作区和版本库里面最新版本的区别:
git log
看到的一大串类似1094adb...
的是commit id
(版本号),和SVN不一样,Git的commit id
不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的commit id
和我的肯定不一样,以你自己的为准。为什么commit id
需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
git log --pretty=oneline
Git必须知道当前版本是哪个版本,在Git中,用HEAD
表示当前版本,也就是最新的提交1094adb...
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
简而言之,执行 git reset HEAD 以取消之前 git add 添加
1 | git reset --hard HEAD^ |
git log
再看看现在版本库的状态:
最新的那个版本append GPL
已经看不到了!好比你从21世纪坐时光穿梭机来到了19世纪,想再回去已经回不去了,肿么办?
办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个append GPL
的commit id
是1094adb...
,于是就可以指定回到未来的某个版本:
1 | $ git reset --hard 1094a |
或者
1 | 查看日志 `cat .git/logs/refs/heads/master`,`cat .git/logs/HEAD` |
你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id
怎么办?
在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^
回退到add distributed
版本时,再想恢复到append GPL
,就必须找到append GPL
的commit id。Git提供了一个命令
1 | git reflog |
用来记录你的每一次命令:
简而言之,执行 git reset HEAD 以取消之前 git add 添加
git reset
1 | $ git reset HEAD^ # 回退所有内容到上一个版本 |
–mixed 为默认,可以不用带该参数,用于重置暂存区的文件与上一次的提交(commit)保持一致,工作区文件内容保持不变**。谨慎使用 –hard 参数,它会删除回退点之前的所有信息。**
1 | git restore --stage readme.txt #丢弃当前暂存区的改动 但是不改变工作区 |
一开始的时候,master
分支是一条线,Git用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点:
每次提交,master
分支都会向前移动一步,这样,随着你不断提交,master
分支的线也越来越长。
当我们创建新的分支,例如dev
时,Git新建了一个指针叫dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上:
你看,Git创建一个分支很快,因为除了增加一个dev
指针,改改HEAD
的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev
分支了,比如新提交一次后,dev
指针往前移动一步,而master
指针不变:
假如我们在dev
上的工作完成了,就可以把dev
合并到master
上。Git怎么合并呢?最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支:
https://www.open-open.com/lib/view/open1328069889514.html
日志
1 | git log --graph --pretty=oneline --abbrev-commit |
执行 git fetch origin master
时,它的意思是从名为 origin 的远程上拉取名为 master 的分支到本地分支 origin/master 中。既然是拉取代码,当然需要同时指定远程名与分支名,所以分开写。
执行 git merge origin/master
时,它的意思是合并名为 origin/master 的分支到当前所在分支。既然是分支的合并,当然就与远程名没有直接的关系,所以没有出现远程名。需要指定的是被合并的分支。
执行 git push origin master
时,它的意思是推送本地的 master 分支到远程 origin,涉及到远程以及分支,当然也得分开写了。
还可以一次性拉取多个分支的代码:git fetch origin master stable oldstable
;
也还可以一次性合并多个分支的代码:git merge origin/master hotfix-2275
得到某个文件修改历史 git log xxxdev
master
工作区某文件恢复到指定版本的时候: git restore -s [hash] xxxx.txt
1 | # rick @ rick-win-manjaro in ~/TMP/GIT-Learn on git:master o [12:02:19] |
工作区某文件恢复到暂存区的版本 git restore xxx
1 | # rick @ rick-win-manjaro in ~/TMP/GIT-Learn on git:master x [11:49:11] |
取消暂存区的内容,不影响工作区
1 | git restore --staged <文件> |
git reset
https://www.jianshu.com/p/cbd5cd504f14
git reset --soft
将HEAD引用指向给定提交。索引(暂存区)和工作目录的内容是不变的,在三个命令中对现有版本库状态改动最小。
git reset --mixed(git reset默认的模式)
HEAD引用指向给定提交,并且索引(暂存区)内容也跟着改变,工作目录内容不变。这个命令会将索引(暂存区)变成你刚刚暂存该提交全部变化时的状态,会显示工作目录中有什么修改。
git reset --hard
HEAD引用指向给定提交,索引(暂存区)内容和工作目录内容都会变给定提交时的状态。也就是在给定提交后所修改的内容都会丢失(新文件会被删除,不在工作目录中的文件恢复,未清除回收站的前提)。
新建分支 , 切换分支,创建跟踪分支
由于git中分支仅仅是一个commit id的别名,所以checkout也可以切换到一个commit id
1 | $ git checkout aaa # 切换到 aaa分支 |
新的switch命令用来接替checkout的功能,但switch不能切换到commit id
1 | $ git switch aaa # 切换到 aaa分支 |
命令查看当前分支
1 | git branch -a #所有分支 |
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
创建+切换分支:git checkout -b <name>
或者git switch -c <name>
1 | git checkout -b totallyNotMaster o/master #tot分支跟踪 远程master |
另一种设置远程追踪分支的方法就是使用:git branch -u
命令,执行:
1 | git branch -u o/master foo |
这样 foo
就会跟踪 o/master
了。如果当前就在 foo 分支上, 还可以省略 foo:
1 | git branch -u o/master |
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
git cherry-pick 当前记录后面跟自定义提交
git cherry-pick <提交号>...
如果你想将一些提交复制到当前所在的位置(HEAD
)
1 | git checkout master; |
git rebase 选分支挂在到指定分支后 -i重新排列
变基
1 | git rebase [前驱分支] [要成为后继分支的分支] |
还可以用来 fast-foward
1 | git checkout mywork |
这些命令会把你的”mywork
“分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到”.git/rebase
“目录中),然后把”mywork
“分支更新 到最新的”origin
“分支,最后把保存的这些补丁应用到”mywork
“分支上。
当’mywork
‘分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除.
命令的形式为:
1 | git rebase [startpoint] [endpoint] --onto [branchName] |
其中,[startpoint]
[endpoint]
仍然和上一个命令一样指定了一个编辑区间(前开后闭),--onto
的意思是要将该指定的提交复制到哪个分支上。
所以,在找到C(90bc0045b)和E(5de0da9f2)的提交id后,我们运行以下命令:
1 | git rebase 90bc0045b^ 5de0da9f2 --onto master |
注:因为[startpoint]
[endpoint]
指定的是一个前开后闭的区间,为了让这个区间包含C提交,我们将区间起始点向后退了一步。
git commit --amend 修改记录,但是不增加一个commit,
移动某个分支名到某个hash
git branch -f [分支名] [hash]
选择父提交记录
操作符 ^
与 ~
符一样,后面也可以跟一个数字。
但是该操作符后面的数字与 ~
后面的不同,并不是用来指定向上返回几代,而是指定合并提交记录的某个父提交。还记得前面提到过的一个合并提交有两个父提交吧,所以遇到这样的节点时该选择哪条路径就不是很清晰了。
Git 默认选择合并提交的“第一个”父提交,在操作符 ^
后跟一个数字可以改变这一默认行为。
获取远程仓库 某个分支 3种方法
1 | 从远程分支 checkout 出来的本地分支,称为_跟踪分支(tracking branch)_。跟踪分支是一种和远程分支有直接联系的本地分支。在跟踪分支里输入git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。反过来,在这些分支里运行 git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。 |
https://blog.csdn.net/weixin_41287260/article/details/98987135
常用的克隆命令应该是这个: git clone <url>
;这个命令其实是下面命令的简写形式:git clone -b master <url>
1. 对于比较少分支的仓库–方法1
思路:先查看远程分支,然后在本地创建和远程仓库同名的分支。
关键命令:git branch dev origin/dev
或git switch -c dev origin/dev
,即新建一个本地分支来跟踪远程的某一分支,创建该分支后,远程分支内容已拉取到本地分支。(或者你可以直接用git checkout -b dev origin/dev
,创建分支,并切换到该分支)
2. 对于比较少分支的仓库–方法2
git clone -b readme url
:下载该仓库的readme分支的内容。
3. 对于比较多分支的仓库
1 | for b in `git branch -r | grep -v -- '->'`; do git branch --track ${b##origin/} $b; done |
删除远程分支
1 | 如果不再需要某个远程分支了,比如搞定了某个特性并把它合并进了远程的 master 分支(或任何其他存放稳定代码的地方),可以用这个非常无厘头的语法来删除它:git push [远程名] :[分支名]。如果想在服务器上删除serverfix 分支,运行下面的命令: |
1 | $ git push origin :serverfix |
1 | 咚!服务器上的分支没了。你最好特别留心这一页,因为你一定会用到那个命令,而且你很可能会忘掉它的语法。有种方便记忆这条命令的方法:记住我们不久前见过的 git push [远程名] [本地分支]:[远程分支] 语法,如果省略 [本地分支],那就等于是在说“在这里提取空白然后把它变成[远程分支]”。 |
添加远程库
要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,命令格式如下:
1 | git remote add [shortname] [url] |
显示某个远程仓库的信息
1 | $ git remote show git@github.com:991688344/Manjaro.git |
git clone git fetch
git fetch
的参数和 git push
极其相似。他们的概念是相同的,只是方向相反罢了(因为现在你是下载,而非上传)
推送到远程仓库 git push
1 | $ git push -u origin master |
由于远程库是空的,我们第一次推送master
分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
要同时为源和目的地指定 <place>
的话,只需要用冒号 :
将二者连起来就可以了:
1 | git push origin <source>:<destination> |
获取远程仓库 git pull = git fetch + git merge
git pull
命令的作用是:取回远程主机某个分支的更新,再与本地的指定分支合并,
将远程存储库中的更改合并到当前分支中。在默认模式下,git pull
是git fetch
后跟git merge FETCH_HEAD
的缩写。
git pull origin foo
相当于:
1 | git fetch origin foo; git merge o/foo |
还有…
git pull origin bar~1:bugFix
相当于:
1 | git fetch origin bar~1:bugFix; git merge bugFix |
简单的多人协作流程
最简单的协作方式之一:先在自己的特性分支中工作一段时间,完成后合并到自己的 master 分支;然后下载合并 origin/master 上的更新(如果有的话),再推回远程服务器。一般的协作流程如图所示:
1. 其他人在我之前修改过远程仓库,本地代码版本落后
git pull
就是 fetch 和 merge 的简写,类似的 git pull --rebase
就是 fetch 和 rebase 的简写!
rebase
单条命令: git pull --rebase
merge
单条: git pull
2. master被锁,需要pull request
tag起锚点作用 , describe寻找最近锚点
git describe
的语法是:
1 | git describe <ref> |
<ref>
可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会以你目前所检出的位置(HEAD
)。
它输出的结果是这样的:
1 | <tag>_<numCommits>_g<hash> |
tag
表示的是离 ref
最近的标签, numCommits
是表示这个 ref
与 tag
相差有多少个提交记录, hash
表示的是你所给定的 ref
所表示的提交记录哈希值的前几位。
当 ref
提交记录上有某个标签时,则只输出标签名称
最近锚点