git:
- 工作区:即自己当前分支所修改的代码,git add XXX之前的!不包括git add XXX和git commit XXX之后的。
- 暂存区:已经git add XXX进去,且未git commit -mXXX的
- 本地分支: 已经git commit -m XXX提交到本地分支的;
初始化并查看仓库当前状态
git init: 初始化本地仓库,会在当前目录下创建一个.git的目录
git status: 查看仓库当前状态
git status -uno:查看仓库当前状态,忽略未跟踪的文件
克隆项目并创建新分支
- 在任何文件夹下,打开git Bash窗口:通过命令
git clone 克隆地址 - 使用命令
git checkout 分支名切换分支 - 基于当前所在分支创建新分支:
git checkout -b 分支名- 创建分支:git branch name [tagname](tagname: 标识标签名)
- 切换分支:git checkout name
- 创建+切换分支:git checkout -b name
- 将本地分支推到远程分支:git push origin name
- 查看所有本地分支:git branch
- 查看所有远程分支:git branch -r
- 查看所有本地分支和远程分支:git branch -a
添加文件进暂存区
git add .:提交所有修改的和新建的数据到暂存区(等于git add -A或者gir add -all)
git add -u(git add -update):提交所有被删除和修改的文件到数据暂存区
git add -A(git add -all):提交所有被删除、被替换、被修改和新增的文件到数据暂存区
git add *.后缀名:提交通配符匹配的对应后缀的文件到暂存区
暂存Stash
git stash/git stash save:将没有提交的内容缓存并移除,而这条缓存名称为最新一次提交的commit -m的内容,如果没有本地提交则是拉远程仓库时的commit内容
git stash save "xxx";暂存文件
git stash list: 查看暂存文件列表
git stash pop:pop出堆栈中最新的内容应用到当前分支上,且会删除堆栈中的记录;如果pop出来的内容有冲突,git会中断此次pop并告知你需要进行冲突解决;
git stash pop stash@{i}指定pop对应的堆栈记录;
git stash show [堆栈记录]:显示与当前分支差异;举例git stash show @{i}加上-p可以看详细差异。
代码回滚
- 在工作区的代码
- git checkout -- a.txt #丢弃某个文件(文件夹);丢弃目标文件所做的修改(删除的文件会恢复回来,修改的文件会回去)
git checkout .放弃对所有文件的修改
注意:git checkout --file命令中,如果没有--,就变成了“切换到另一个分支的命令”
- 本地新增了一些文件(并没有 git add 到暂存区),想放弃修改:
-
- 单个文件/文件夹:
rm -rf filename - 所有文件:
git clean -xdf
- 单个文件/文件夹:
- 代码git add到暂存区,并未commit提交
- git reset HEAD
- git reset HEAD a.txt(此时回退回来仅仅是把添加到暂存区的的内容回退到工作区,即此时相关文件的内容仍然没有修改,若还需要进一步回退内容,则使用git checkout -- 来回退内容)
这个命令仅改变暂存区,并不改变工作区,这意味着在无任何其他操作的情况下,工作区的实际文件同该命令运行之前无任何变化
- git commit 到本地分支,但没有git push到远程
- git log #得到需要回退一次的commit id
- git reset --hard <commit_id> 回到你想要的某个版本
- git reset --hard HEAD^ 回到最新的一次提交
- git push把修改提交到远程仓库
- 通过git reset 是直接删除执行的commit
-
- git log 得到需要回退的commit id
- git reset --hard <commit_id>
- git push origin HEAD --force强制提交一次,之前错误的提交就从远程仓库删除
- 通过 git revert 是用一次新的commit来回滚之前的commit
-
- git log
- git revert <commit_id>:撤销指定的版本,撤销也会作为一次提交进行保存
- git revert 和 git reset的区别
-
- git revert是用一次新的commit来回滚之前的commit,此次提交之前的commit都会被保留
- git reset是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除
删除文件
git中,删除也是一个修改;
首先新建一个test.txt文件,添加并添加并提交到仓库(即模拟创建仓库中已经存在的一个文件);
- 当我们使用命令
rm test.txt把目录下的文件删除;此时工作区和版本库变得不一致;使用git status查看状态,指出删除了test.txt文件;现在有两种操作:1、确定从版本库中删除文件;2、从暂存区把误删的文件恢复 -
- 确定从版本库中删除文件
-
- 使用git rm 删除文件并git commit提交
- 从暂存区把误删的文件恢复
-
- 使用git checkout --file从暂存区恢复误删的文件(本质还是丢弃工作区的改动)
拉取远端代码(git pull与git pull --rebase)
git pull·=== git fetch + git merge FETCH_HEAD
git pull --rebase === git fetch + git rebase FETCH_HEAD
两种的区别是在fetch之后的操作,merge与rebase的不同。 假设当前master的提交如下:
如果你或者你的同事在cid2点,开发进度是cid20(或者突然拉出一个分支,假设是tmp分支),此时要把cid20提交到master
在master执行git merge tmp,然后会得到如下结果:
新增了一次提交记录cid6,似乎也没有什么问题,如果装了小乌龟,查看提交日志,可能就是下面的样子:
业务上体现可能是这样:
merge提交的缺陷:
- git 提交记录上分不清每种业务的commit。
- graph体现的开发提交的业务记录,在master上比较混乱。
- 回滚(如果需要)在当前模式下,繁琐且容易出错。
git rebase
在master执行git rebase tmp之后,操作分支如下:
二者对比可知,rebase没有产生新的节点,使用rebase的git演进路线(提交树)是一直向前的,这样在版本回退时也很容易,用merge的git路线是跳跃的,如果版本回退你也找不到自己想要的版本,如果merge时出现了冲突就麻烦了,当前merge就不能继续进行下去,需要手动修改冲突内容后,add,commit,push而rebase操作的话,会中断rebase,同时会提示去解决冲突,解决冲突后,再执行git rebase --continue继续操作,再push; 想要更好的提交树,建议使用rebase操作会更好一点,这样可以线性的看到每一次提交,并且没有增加提交节点;不过有些项目不建议使用rebase,得看公司与项目的规定。
git pull --rebase 之后如果有合并冲突,使用一下三种方式处理这些冲突:
-
git rebase --abort 会放弃合并,回到rebase操作之前的状态,之前的提交不会丢弃;
-
git rebase --skip则会将引起冲突的commits丢弃掉(慎用)
-
git rebase --continue合并冲突,结合“git add 文件”命令一起修复冲突,提示开发者,一步一步地解决冲突
git log
- git log在不传参数的情况下,默认查看当前分支的提交记录,显示以下4个字段信息:
-
- 提交对象(commit)的完整哈希字串
- 提交这信息(作者的名字和电子邮件地址)
- 提交时间
- 提交说明
- git log后面可以指定查看哪个分支/tag的提交记录
-
- git log origin/master
- git log test
- git log v1.0.0
- git log --oneline用法:使用--oneline,git log信息会变得非常简洁,默认只显示简短的commit id 和提交注释
- git log --format用法
-
- 语法:git log --format=“XXX”
- 使用实例:git log --format=‘commit id: %h,commit annotation:%s'
- git log --prety用法
-
- git log --pretty实际等价于git log --online
远程名称
- 一个本地仓库可以关联多个远程仓库的;
git remote add origin <repo_address>
git remote add内部做了什么默默无闻的工作呢?他其实是往.git/config中写入了一个叫[remote "origin"]配置;
即git remote add命令,添加了一个叫做origin的远程名称:
- 其中url参数,表示该远程名称对应的远程仓库地址。
- 其中fetch参数分为两部分,以冒号:进行分割,冒号左边标识本地仓库文件夹,冒号右边表示远程仓库在本地的副本文件夹。里面的加号+表示往里面添加数据的意思。
当使用git fetch origin时,Git将远程仓库下的所有分支拉取到本地的refs/remotes/origin/目录下,然后git merge时,它会把refs/remote/origin/目录下的对应分支合并到refs/heads/目录下对应分支上。
如果本地的仓库时通过git clone下来的,Git 会默认将远程仓库命令为origin,自动帮你关联上远端仓库(可在.git/config文件中看到已有[remote "origin"]配置项了),因此Commit之后就能直接push了。
- 注意:origin只是一个名称(别名),用于指向远程仓库。这个别名是可以自行修改的,比如命令为foo,bar等。使用别名的好处是【简单,方便、好记(就像网址和IP的关系)】
-
- 既然是别名,就是可修改的;
-
- 新增远程名称(一个本地仓库,可以关联多个远程仓库):git remote add
- 删除已存在远程名称: git remote rm
- 更新远程名称关联的远程仓库:git remote set-url
- 修改远程名称(也可以先删除再添加):git remote rename
git remote -v:查看本地仓库关联的远程仓库信息;也可以在文件.git/config文件查看
远程分支
远程分支是远程仓库对应分支在本地的一个副本。如常见的origin/master、origin/main、origin/develop等都是远程分支,可以在.git/refs/remotes目录下看到。
git branch:查看所有本地分支
git branch -r:查看所有远程分支
git branch -a: 查看所有本地分支和远程分支
HEAD
- HEAD存放于本地仓库的.git/HEAD文件里面,利用cat命令:
cat .git/HEAD可以看到他的内容 - HEAD是对当前Commit-ID的引用;如果切换分支,HEAD的内容会跟着改变。
- 除了git commit之外,git checkout,git reset等命令都会影响HEAD的指向。
-
- 当使用git commi时,HEAD会跟着移动,并指向最新的Commit-ID。
- 当使用git checkout时,HEAD会移动并指向对应分支的最新一个Commit-ID。
- 当使用git reset时,HEAD会移动至对应分支的某个Commit-ID。请注意git reset --hard可以HEAD和Branch移动至任何地方。git reset的本质就是移动HEAD来达到撤销的目的。
origin/HEAD
origin/HEAD也是一个[远程分支],其中origin则对应远程名称。一般情况下,origin/HEAD总是指向仓库的【默认分支】。假设我们的远程默认分支为main。那么远程仓库在本地的副本,origin/HEAD就是相当于origin/main。Git提供了以下命令让我们去修改origin/HEAD的指向(可通过git remote set-head -h 查看):以下中文解释,假定了远程名称为origin。
git remote set-head <remote-name> -a:将origin/HEAD设为远程仓库的默认分支(-a 即--auto)
git remote set-head <remote-name> <branch-name>:将origin/HEAD设为某个远程分支
比如将git remote set-head origin dev,将origin/HEAD指向远程的dev分支,相当于origin/dev
git remote set0head <remote-name> -d:删除origin/HEAD(-d即 --delete)
ORIG_HEAD
在 .git 目录下,有一个ORIG_HEAD的文件,当我们进行了一些【危险操作】时,比如 git reset, git merge, git rebase 等操作时,Git 会将当前的HEAD指向的Commit-ID原值保存至ORIG_HEAD文件内。需要注意的是,类似git commit 等操作并不会更新ORIG_HEAD的内容。
这样的话,假设我们执行了一些【误操作】时,可以利用 git reset --hard ORIG_HEAD回退至上一步。(ORIG_HEAD:记录高危操作前的Commit-ID;可以使用命令:cat .git/ORIG_HEAD)
如果想吃后悔药了,可以通过 git reset --hard ORIG_HEAD进行回退
FETCH_HEAD
其中 FETCH_HEAD 和 git fetch有关,也是关键部分。
- FETCH_HEAD 指的是某个分支在远程仓库上最新的状态,每一个执行过git fetch操作的本地仓库都会存在一个FETCH_HEAD 列表,这个列表保存在 .git/FETCH_HEAD 文件中。FETCH_HEAD 文件中的每一行对应着远程仓库的一个分支。当前本地分支执行的FETCH_HEAD 就是该文件中的【第一行】对应的分支。
git查看当前仓库地址
`git remote show origin`
文章参考
https://developer.aliyun.com/article/919354
https://blog.csdn.net/the_power/article/details/104651772/