<pre cid="n0" mdtype="meta_block" class="md-meta-block md-end-block" style="box-sizing: border-box; overflow: hidden auto; font-family: var(--monospace); font-size: 13.6px; min-height: 0.8rem; white-space: pre-wrap; background-color: rgb(247, 247, 247); display: block; width: inherit; padding: 1rem; line-height: 1.45; border: 0px; border-radius: 3px; color: rgb(119, 119, 119); margin-top: 0px !important; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">layout: post
title: "Git原理及用法简介"
date: 2017-05-16 10:36
toc: true
comments: true
categories: 技术学习
tags:
- Git
</pre>
安装Git
安装完成后,还需要最后一步设置,在命令行输入:
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n4" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;"> git config --global user.email "siyuanzhou@163.com"</pre>
由于你的本地 Git 仓库和 GitHub 仓库之间的传输是通过SSH加密的,所以我们需要配置验证信息:
使用以下命令生成 SSH Key:key在用户/.ssh文件夹下
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n8" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">$ ssh-keygen -t rsa -C "youremail@example.com"</pre>
Git原理
所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
Git 和其他版本控制系统的主要差别在于,Git 只关心文件数据的整体是否发生变化,Git 并不保存这些前后变化的差异数据。实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一链接。Git 的工作方式就如下图所示。 [图片上传失败...(image-ca89e9-1676555834847)]
工作区、暂存区、版本库、远程库
工作区(Working Directory)
在电脑中能看到的目录,比如我建立的gittest就是一个工作区
版本库(Repository)
工作区中的隐藏目录.git
,就是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
[图片上传失败...(image-814f1d-1676555834847)]
需要提交的文件经过add后先都放到暂存区index(或者叫stage)中,然后经过commit指令,一次性提交暂存区的所有修改到head。一旦提交后,同时若对工作区没有做任何修改,那么工作区就是干净的(working directory clean)
文件内容并没有真正存储在索引(.git/index)或者提交对象中,而是以blob的形式分别存储在数据库(.git/objects),并用SHA-1值来校验。 索引文件用识别码列出相关的blob文件以及别的数据。对于提交来说,以树(tree)的形式存储,同样用对于的哈希值识别。树对应着工作目录中的文件夹,树中包含的 树或者blob对象对应着相应的子目录和文件。每次提交都存储下它的上一级树的识别码。
重要的 .git 目录
当一个新目录或已有目录执行git init
时,Git会创建一个.git
目录。这个目录包含了几乎所有Git存储和操作的对象。若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n23" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">description文件:仅供GitWeb程序使用
config文件:包含项目特有的配置选项
info目录:包含一个全局性排除(global exclude)文件,用以放置那些不希望被记录在 .gitignore文件中的忽略模式(ignored patterns)
hooks目录:包含客户端或服务端的钩子脚本(hook scripts)
HEAD文件:指示目前被检出的分支
index文件:保存暂存区信息
objects目录:存储所有数据内容
refs 目录:存储指向数据(分支)的提交对象的指针</pre>
Git相关命令
[图片上传失败...(image-eceb42-1676555834847)]
workspace: 本地的工作目录。(记作 工作区)
index:缓存区域,临时保存本地改动。(记作 暂存区)
local repository: 本地仓库,只想最后一次提交 HEAD。(记作 版本库)
remote repository:远程仓库。(记作 远程库)
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n35" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">git init命令,初始化一个Git仓库
git add <file>,注意,可反复多次使用,添加多个文件;
git commit -m <message>,提交到工作区。
git status 比较工作区和缓存区(index或者stage)之间的差别
git diff来查看工作区和暂存区差异
git diff --cached来查看暂存区和仓库的差异
git clone,克隆一个仓库,Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快
git checkout -- file 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用版本库里的版本替换工作区的版本
git reset --hard commit_idHEAD指向的版本就是当前版本,Git允许在版本历史间穿梭
git log可以查看提交历史,以便确定要回退到哪个版本
git reflog查看命令历史,以便确定要回到未来的哪个版本
git reset HEAD <file> 当你不但改乱了工作区某个文件还add后,可以把暂存区的修改撤销掉(unstage)
git rm用于删除已经add但没commit(index区)的一个文件
git remote add origin git@server-name:path/repo-name.git 要关联一个远程库
git push -u origin master第一次推送master分支的所有内容 origin表示远程库
git pull --rebase origin master 把远程库中的更新合并到本地库中,–rebase的作用是取消掉本地库中刚刚的commit,并把他们接到更新后的版本库之中
git remote -v 远程库信息
命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id;
命令git tag -a <tagname> -m "blablabla..."可以指定标签信息;
命令git tag可以查看所有标签
命令git push origin <tagname>可以推送一个本地标签;
命令git push origin --tags可以推送全部未推送过的本地标签;
命令git tag -d <tagname>可以删除一个本地标签;
命令git push origin :refs/tags/<tagname>可以删除一个远程标签。</pre>
[图片上传失败...(image-d0a767-1676555834847)]
Git分支管理
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n38" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>或者git switch <name>
创建+切换分支:git checkout -b <name>或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
看分支合并图:git log --graph
合并分支时,加上--no-ff参数就可以用普通模式合并,这样进行了一次新的 git commit 操作
git stash把当前工作现场“储藏”起来,等以后git stash pop恢复现场后继续工作
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动
git branch --set-upstream branch-name origin/branch-name建立本地分支和远程分支的关联
git push origin branch-name从本地推送分支,若失败,先用git pull
抓取远程的新提交;
git checkout -b branch-name origin/branch-name在本地创建和远程分支对应的分支(分支名最好一致)
开发一个新feature,最好新建一个分支
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。
本地新建的分支如果不推送到远程,对其他人就是不可见的</pre>
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。HEAD
指向的就是当前分支。 一开始的时候,master
分支是一条线,Git用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点:
[图片上传失败...(image-4268f4-1676555834847)]
每次提交,master
分支都会向前移动一步,这样,随着你不断提交,master
分支的线也越来越长, 当我们创建新的分支,例如dev
时,Git新建了一个指针叫dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上:
[图片上传失败...(image-360395-1676555834847)]
Git创建一个分支很快,因为除了增加一个dev
指针,改改HEAD
的指向,工作区的文件都没有任何变化!不过,从现在开始,对工作区的修改和提交就是针对dev
分支了,比如新提交一次后,dev
指针往前移动一步,而master
指针不变:
[图片上传失败...(image-21804e-1676555834846)]
假如我们在dev
上的工作完成了,就可以把dev
合并到master
上。Git怎么合并呢?最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
[图片上传失败...(image-8aaba5-1676555834846)]
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支。
合并操作( merge )只对对当前所在分支产生影响;无论是否存在冲突,合并之后,feature分支都不会发生变化。
[图片上传失败...(image-98663b-1676555834846)]
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
[图片上传失败...(image-cddbde-1676555834846)]
多人协作
多人协作的工作模式通常是这样:
首先,可以试图用
git push origin
推送自己的修改;如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并;如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用
git push origin
推送就能成功
开源做贡献
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n68" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">在GitHub上,可以任意Fork开源仓库;
自己拥有Fork后的仓库的读写权限;
可以推送pull request给官方仓库来贡献代码。</pre>
图解命令
基本用法
[图片上传失败...(image-fe0c50-1676555834846)]
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n72" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">git add files 把当前文件放入暂存区域。
git commit 给暂存区域生成快照并提交。
git reset -- files 用来撤销最后一次git add files,你也可以用git reset 撤销所有暂存区域文件。
git checkout -- files 把文件从暂存区域复制到工作目录,用来丢弃本地修改。</pre>
也可以跳过暂存区域直接从仓库取出文件或者直接提交代码。
[图片上传失败...(image-261ac2-1676555834846)]
<pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="" cid="n75" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">git commit -a 相当于运行 git add 把所有当前目录下的文件加入暂存区域再运行。git commit.
git commit files 进行一次包含最后一次提交加上工作目录中文件快照的提交。并且文件被添加到暂存区域。
git checkout HEAD -- files 回滚到复制最后一次提交。</pre>
git pull –rebase origin master
error:failed to push some refs to问题
在github库中对某个文件进行了在线的编辑,并且没有同步到本地库,之后我在本地库添加了文件test.txt,并想提交到github,出现以下错误:error:failed to push some refs to
[图片上传失败...(image-8ccf26-1676555834846)]
git pull –rebase origin master意为先取消commit记录,并且把它们临时 保存为补丁(patch)(这些补丁放到”.git/rebase”目录中),之后同步远程库到本地,最后合并补丁到本地库之中。
[图片上传失败...(image-dfcd9b-1676555834846)]
约定
[图片上传失败...(image-5bc7b6-1676555834846)]
绿色的5位字符表示提交的ID,分别指向父节点。分支用橘色显示,分别指向特定的提交。当前分支由附在其上的HEAD标识。 这张图片里显示最后5次提交,ed489是最新提交。 master分支指向此次提交,另一个maint分支指向祖父提交节点。
git diff
有许多种方法查看两次提交之间的变动。下面是一些示例。
[图片上传失败...(image-7b4195-1676555834846)]
git commit
提交时,git用暂存区域的文件创建一个新的提交,并把此时的节点设为父节点。然后把当前分支指向新的提交节点。下图中,当前分支是master。 在运行命令之前,master指向ed489,提交后,master指向新的节点f0cec并以ed489作为父节点。
[图片上传失败...(image-37406f-1676555834846)]
即便当前分支是某次提交的祖父节点,git会同样操作。下图中,在master分支的祖父节点maint分支进行一次提交,生成了1800b。 这样,maint分支就不再是master分支的祖父节点。此时,合并(merge)是必须的。
[图片上传失败...(image-e965ed-1676555834846)]
如果想更改一次提交,使用 git commit --amend
。git会使用与当前提交相同的父节点进行一次新提交,旧的提交会被取消。
[图片上传失败...(image-39a4ac-1676555834846)]
git checkout
checkout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。
当给定某个文件名(或者打开-p选项,或者文件名和-p选项同时打开)时,git会从指定的提交中拷贝文件到暂存区域和工作目录。比如,git checkout HEAD~ foo.c
会将提交节点HEAD~(即当前提交节点的父节点)中的foo.c
复制到工作目录并且加到暂存区域中。(如果命令中没有指定提交节点,则会从暂存区域中拷贝内容。)注意当前分支不会发生变化。
[图片上传失败...(image-57e432-1676555834846)]
当不指定文件名,而是给出一个(本地)分支时,那么HEAD标识会移动到那个分支(也就是说,我们“切换”到那个分支了),然后暂存区域和工作目录中的内容会和HEAD对应的提交节点一致。新提交节点(下图中的a47c3)中的所有文件都会被复制(到暂存区域和工作目录中);只存在于老的提交节点(ed489)中的文件会被删除;不属于上述两者的文件会被忽略,不受影响。
[图片上传失败...(image-19cb28-1676555834846)]
如果既没有指定文件名,也没有指定分支名,而是一个标签、远程分支、SHA-1值或者是像master~3类似的东西,就得到一个匿名分支,称作detached HEAD(被分离的HEAD标识)。这样可以很方便地在历史版本之间互相切换。比如说你想要编译1.6.6.1版本的git,你可以运行git checkout v1.6.6.1
(这是一个标签,而非分支名),编译,安装,然后切换回另一个分支,比如说git checkout master
。
[图片上传失败...(image-68ab41-1676555834846)]
HEAD标识处于分离状态时的提交操作
当HEAD处于分离状态(不依附于任一分支)时,提交操作可以正常进行,但是不会更新任何已命名的分支。(你可以认为这是在更新一个匿名分支。)
[图片上传失败...(image-78c442-1676555834846)]
一旦此后你切换到别的分支,比如说master,那么这个提交节点(可能)再也不会被引用到,然后就会被丢弃掉了。注意这个命令之后就不会有东西引用2eecb。
[图片上传失败...(image-b67e3b-1676555834846)]
但是,如果你想保存这个状态,可以用命令git checkout -b *name*
来创建一个新的分支。
[图片上传失败...(image-dc6849-1676555834846)]
Reset
reset命令把当前分支指向另一个位置,并且有选择的变动工作目录和索引。也用来在从历史仓库中复制文件到索引,而不动工作目录。如果不给选项,那么当前分支指向到那个提交。如果用--hard
选项,那么工作目录也更新,如果用--soft
选项,那么都不变。
[图片上传失败...(image-a1caa2-1676555834846)]
如果没有给出提交点的版本号,那么默认用HEAD。这样,分支指向不变,但是索引会回滚到最后一次提交,如果用--hard
选项,工作目录也同样。
[图片上传失败...(image-d33885-1676555834846)]
如果给了文件名(或者 -p
选项), 那么工作效果和带文件名的checkout差不多,除了索引被更新
[图片上传失败...(image-58eb29-1676555834846)]
Merge
merge 命令把不同分支合并起来。合并前,索引必须和当前提交相同。如果另一个分支是当前提交的祖父节点,那么合并命令将什么也不做。 另一种情况是如果当前提交是另一个分支的祖父节点,就导致fast-forward合并。指向只是简单的移动,并生成一个新的提交。
[图片上传失败...(image-40198c-1676555834846)]
否则就是一次真正的合并。默认把当前提交(ed489 如下所示)和另一个提交(33104)以及他们的共同祖父节点(b325c)进行一次三方合并。结果是先保存当前目录和索引,然后和父节点33104一起做一次新提交。
[图片上传失败...(image-b7246c-1676555834846)]
如下图,1bdd3be5修改自ba8beb31,d6c1b0e2也修改自ba8beb31。 三方合并如下图, 只需要把差异项合并 ,得到最终12325为合并结果,下图中没有发生冲突
[图片上传失败...(image-9ddff7-1676555834846)]
Cherry Pick
cherry-pick命令"复制"一个提交节点并在当前分支做一次完全一样的新提交。
[图片上传失败...(image-487017-1676555834846)]
Rebase
衍合是合并命令的另一种选择。合并把两个父分支合并进行一次提交,提交历史不是线性的。衍合在当前分支上重演另一个分支的历史,提交历史是线性的。 本质上,这是线性化的自动的 cherry-pick
[图片上传失败...(image-1943e2-1676555834846)]
上面的命令都在topic分支中进行,而不是master分支,在master分支上重演,并且把分支指向新的节点。注意旧提交没有被引用,将被回收。要限制回滚范围,使用--onto
选项。下面的命令在master分支上重演当前分支从169a6以来的最近几个提交,即2c33a。
[图片上传失败...(image-8505b9-1676555834846)]
同样有git rebase --interactive
让你更方便的完成一些复杂操作,比如丢弃、重排、修改、合并提交。
.gitignore文件
在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如无,则需自己手工建立此文件)。这个文件每一行保存了一个匹配的规则。
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="" cid="n135" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;"># 此为注释 – 将被 Git 忽略
.a # 忽略所有 .a 结尾的文件
!lib.a# 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/# 忽略 build/ 目录下的所有文件,可以为子目录
doc/.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt 1234567
配置规则:
以 # 开头行为注释
以斜杠“/”开头表示目录;
/target/ 过滤根目录的 target 文件夹
target/ 过滤任何目录包含的 target 文件夹
以星号“*”通配多个字符;
*.zip 过滤所有.zip文件
以问号“?”通配单个字符;
以方括号“[]”包含单个字符的匹配列表;
以叹号“!”表示不忽略(跟踪)匹配到的文件或目录;
/doc/
!/doc/common.doc
此外,git 对于 .ignore 配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效;
被过滤掉的文件就不会出现在你的GitHub库中了,当然本地中还有,只是push的时候不会上传。</pre>
规则很简单,不做过多解释,但是有时候在项目开发过程中,突然心血来潮想把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,原因是.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:
<pre class="md-fences mock-cm md-end-block" spellcheck="false" lang="" cid="n137" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit; background-repeat: inherit;">git rm -r --cached .
git add .
git commit -m 'update .gitignore</pre>
参考来源:
本文部分节选自图解算法
本文部分节选自廖雪峰Git教程