- git config --global alias.st status —— 这样st就是status的意思了,以后git status只需要输入git st。
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
工作流程与代码
- 第一步,获取代码
- 如果是已有代码,需要纳入git体系
git init
+git checkout -b develop
+git add .
+git commit -m ''
+git remote add origin xxx
+git push origin master:develop
完成初始化git并在本地develop分支提交,然后上传代码到远程仓库的develop分支。 - 如果是已在git远程仓库中的代码,则
git clone xxx
+git branch -a
+git checkout --track origin/develop
+git checkout -b feature-login (origin/feature-login)
,完成克隆代码并从远程分支develop分支检出本地develop分支,并创建(检出远程)feature分支在本地进行功能的开发。
- 如果是已有代码,需要纳入git体系
- (合作开发)每天开始工作前,要做的是把代码从远程仓库中
git pull (--rebase)
- 开发过程(本地)
上次提交过后,这次又写了一些代码,但是写错了想退回去之前的工作空间状态
开发时想查看git状态和信息git reset [版本号] 是回退本地仓库但工作空间不变。 git reset --hard xxx 回退本地仓库并还原工作空间到 某次提交过后状态 。 git reset --hard [filename/版本号] git checkout [文件名] 退回到 上次暂存区(add)状态 的工作目录。
每天干完活之后git status git log git reflog git blame filename 查看本文件最后一次修改记录
(工作空间栈)如果你没保存修改的内容就切换分支,则会丢失本次修改(被目标branch的最新commit重 写)。但是你又想切换分支怎么办?可以使用储藏功能来保存工作现场,然后再切换分支,等需要时候再恢复工作空间git add . git commit -m 'update xxxx' git push <remote> <localbranch:remotebranch> 或git push -u <remote> <localbranch:remotebranch>以后就只需要在本分支直接push origin即可
当功能分支开发完毕之后,需要合并到开发分支上并上传代码,同时删除本地和远程的功能分支git stash —— 隐藏当前工作空间的修改 git stash list —— 列出stash 记录 git stash -pop 恢复现场并删除一个stash记录。 git stash apply —— 恢复现场,但不删除stash记录 git stash drop —— 删除一条stash记录
阶段性开发完成,可以发布release了//以下两步的作用是保证你本地的feature-login分支的代码为最新,因为有可能你是和别人合作开发的该功 能,如果你刚更新过或者你是一个人在开发则可以省略此操作 git checkout feature-login //切换到本地feature-login分支 git pull --rebase //拉取最新代码 git checkout develop //切换到本地develop分支 git pull --rebase //拉取最新的远程origin/develop分支代码,因为可能已经有人提交了代码 git merge --no-ff feature-login //从本地feature-login分支合并代码,--no-ff为禁止fast-farward模式 git push //推送到远程分支 //代码已经合并完,可以删除本地特性分支和远程特性分支 git branch -d feature-login //删除本地feature-login特性分支 git branch -r -d origin/feature-login //删除远程origin/feature-login特性分支
git checkout develop //切换本地分支到develop分支 git pull //拉取远程Git仓库中的最新的develop分支的代码 git checkout -b release-1.2.0 //创建本地发布分支 git tag tagname <first-10-chars-commid-id>—— 为最后一次 <某次>commit打tag 或git tag -a <tagname> -m "blablabla..."—— 带有注释的标签。 git push -u origin release-1.2.0 //推送本地发布分支到远程Git仓库( git push origin --tags 退送所有本地标签。git tag -d tagname—— 删除本地tag)
镇帖之宝
下载速度太慢的解决方法:修改Host
https://www.ipaddress.com/在里面分别查询一下域名ip
- github.com
- github.global.ssl.fastly.net
得到:
- 140.82.114.3 github.com
- 199.232.69.194 github.global.ssl.fastly.net
然后添加这两个句话添加到末尾 C:\Windows\System32\drivers\etc
然后到cmd中刷新DNS缓存:ipconfig /flushdns
收工!!!
git-bash使用
- cat echo等都可以用
- 选中复制,中键黏贴。
- 更新环境变量HOME内容为gitws地址,下载Gitbash:https://git-scm.com/downloads一路安装。
- 更新ssh密钥,指令:ssh-keygen -t rsa -C "your_email@youremail.com",不输入文件名也行一路回车。然后到。然后在ws下的.ssh目录下有公钥.pub和私钥。进入到github上点开设置-ssh和gpg密钥,用记事本打开.pub然后把内容上传title可以随意。bash中键入ssh -T git@github.com 测试是否成功验证
- 配置环境:用户名git config --global user.name yourusername 和邮箱git config --global user.email yourusername@email.com。相当于机器自报家门
- 可以下载带有UI的git,比如下载source-tree,在sourcetree中使用ssh的方法1
几个名词的解释:
workspace(WS):工作区,程序员进行开发的地方。平常我们开发就是拷贝远程仓库的一个分支,基于此分支进行开发。在这里我们编写文件删除文件...,但这些文件在没被add到index中的时候是不受git管理的。而你pull下来的东西也不会改变你的工作区而是本地仓库,而是改变你工作区.git的文件夹中的记录。你push的也不是工作区的而是add后commit到本地仓库。区分本地仓库和工作区的区别,一般说的操作都是说本地仓库而不是工作区,比如回退是指本地仓库回退到某次commit的状态而不是ws。但pull是把远程仓库的拉取到WS
-
index(staged暂存):暂存区,将工作区的文件通过git add加入git管理体系中。可以通过git status查询暂存区状态
commit:快照,就是一些修改的记录。
repository :仓库。github上的一个项目;
Fork:叉子。在别人的github页面,点击fork按钮,将别人的仓库复制一份到自己的仓库,此时我们自己的github就有一个一模一样的仓库,但是URL不同。你可以自行修改项目内容而不会影响原始的库,也可以将自己的修改通过合并请求(a pull request)的方式请求原始库的开发者更新你的修改;
Clone:克隆。将github中的仓库克隆到自己电脑本地仓库中;
Push:推。将本地仓库推送同步到远程github仓库(需要权限)
Pull request:将你github仓库的修改同步到代码原始开发者那(fork过来的那个人)
fetch:去取来。也就是说当你fork了别人的项目,你可以pull request合并你的代码到作者代码。同样,作者修改了自己的代码你也可以fetch下来同步到自己的本地仓库。
branches:分支。
注:如果你没被作者授权为他某个仓库的合作者,你不能push。只能fork过来然后修改完pull request请求作者合并,作者通过请求后就能合并代码。
图文结合:
基本操作
可见本地创建一个工作区,使用git add 指令会添加到暂存区,再使用commit 把暂存区的文件提交到本地仓库。还可以使用remote add origin 添加远程origin。然后git push (-u)(第一次提交带u) origin master。当然了上面的远程仓库是你在github上创建的,如果是新项目,必须新建一个仓库。
通用操作
- git log <–pretty=oneline>
—— 查询某个git仓库的commit记录。包含唯一hash标识、提交者(git config usr.name/user.email配置的内容)、时间戳。
1.1 git log --graph --oneline --decorate --all 可以查看图形化的分支提交记录
1.2 git log --graph --pretty=oneline --abbrev-commit
—— 同上 - git reflog 查询完整log
- git status 查看文件的修改情况,提交情况。
- git blame filename 查看文件的最后修改记录,包括修改者,修改时间,修改内容
- git reflog 显示每一次操作指令。
本地仓库到自己github:
github上创建一个远程仓库。
git init
—— 初始化一个目录为工作区,创建本地仓库。git add ./文件名
—— 添加文件到工作空间暂存区。-
git commit -m '备注'
—— 将工作区的暂存区文件提交到本地仓库并附带备注。图片说明了哪个分支,哪个commit_Id,做了哪些备注。有几个文件被修改,插入了几行新的。
git remote add origin(该为主机名,可以自己命名) url
—— 本地仓库添加一个远程主机并命名。git push <-u>(设置默认远程分支=写的远程分支) origin(远程主机名) 本地分支名<:远程分支名>(不写为同分支名,如不存在则新建)
——将本地仓库分支推送到远程仓库的分支(需要有权限,如果不是自己的github的仓库,则需要别人授权仓库的contributor权限)。此外url可以有多种格式:https://github.com/用户名/远程仓名.git 、git://开头的靠ssh协议、或git@github.com:用户名/远程仓名.git。
6.1 git push
—— 推送当前分支,只有1个远程跟踪分支或有默认主机时使用。当多个用户共同开发的时候,可能你的提交比你的同伴晚,所以你需要先pull下最新版本,然后在本地合并后继续push。
6.2 git branch --set-upstream-to=origin/dev dev
—— 继续6.1。pull失败时,可能是本地分支dev没有和远程分支建立连接,不知道你从哪个分支pull到哪个分支。git reset hash码(git log显示的commit标识)
—— 回退本地仓库到某次commit后的状态(也就是移动HEAD指针到某次commit处)。而如果要回退到回退处之后的版本(当前和会退前之间的commit点),git log是查不到版本号的,用git reflog查询每一次指令。
7.1 git reset -hard 版本号
—— 是使得WS也回退到某次commit的样子,而不只是本地仓库。
7.2 git reset - hard HEAD^
—— HEAD指向当前版本,一个表示上一个版本。两个^就是上上版本,或者HEAD~2。
7.3 git reset HEAD filename
—— 将暂存区的东西测撤回到工作区git restore <filename>
—— 放弃、撤回、恢复工作区中某个文件的修改。
8.1 git restore --staged <filename>
—— 当你add某个文件到暂存区,你要使用这个指令来从暂存区中移除该文件,然后再使用8的指令来恢复该文件。git checkout -- filename
—— 检回文件。丢弃工作区修改到最近一次add或commit状态。即将工作空间的文件恢复到本地仓库的版本。如果工作空间的文件修改后被add到暂存区了,则恢复到暂存区状态。除非使用8.1从暂存区退出,然后才能恢复到本地仓库版本。
9.1 git checkout commmit_id 检出某个版本的信息。这也会直接把HEAD移到那个版本导致git log和commit记录没了。需要git reflog 和git reset --hard commit_id 回到现在git tag tagname <first-10-chars-commid-id>
—— 为最后一次 <某次>commit打tag
10.1 git tag -a <tagname> -m "blablabla..."
—— 带有注释的标签。
10.2 git show tagname
—— 展示tag对应的commit修改的内容
10.3 git push origin <tagname>
—— 推送一个本地标签到远程仓库
10.4 git push origin --tags
—— 推送本地所有标签到远程
10.5 git tag -d tagname
—— 删除本地tag
获取别人的代码到自己github并本地仓库修改:
- 在github上fork别人的代码到自己的github上作为仓库。
- git clone 仓库网址url
—— 克隆一个一模一样的远程库到本地库。当然不一定要从主机github上克隆。且自动关联主机且默认远程仓库主机名叫origin。使用git clone -o 名字 url 可以修改默认名。 - 本地到自己github操作见以上。
- 添加一个远程主机关联(使用原作者url)
- git fetch origin(远程主机名) master(分支名,不写=所有分支,下同)
—— 获取原作者某个分支的最新版本。 - git branch -a(ll)
—— 查看所有分支。 - git diff 源分支 目标分支或者git log -p master(本地分支名)..origin(远程主机名)/远程分支名
—— 比较本地和某个关联的差别。 - git merge origin(远程主机名)/远程分支名
—— 合并当前本地分支和远程分支。 - git pull origin(远程主机名) master(远程分支名) :本地分支名
—— 相当于 fetch+merge。缺少检查差别的这步。如果远程分支和本地分支一个名字则:本地分支可以省略。 - git remote -v :查看远程主机名列表
WS未提交当前内容却想进行其他工作事项时。
- git stash
—— 隐藏当前工作空间的修改 -
git stash list
—— 列出stash 记录
3 git stash -pop 恢复现场并删除一个stash记录。
3.1 git stash apply
—— 恢复现场,但不删除stash记录
3.1 git stash drop
—— 删除一条stash记录
如果你没保存自上次commit后修改的内容就切换分支,则回丢失本次修改(被目标branch的上次commit重写而丢失)。但是你又想切换分支怎么办?可以使用储藏功能来保存工作现场
分支管理
多人协作中,github上存放镜像,其中有master分支是要发布的版本,其余分支是并行的,可以合并到主分支上。各分支是不同开发者从他们的本地仓库分支推上来的。
分支
git使用一个"链表"来记录仓库里的每次"修改记录"(提交)。用于保存提交的记录链表是可以被命名的,它就是我们常说的分支。
如master分支,可以当作一个链表头,指向最新一次commit。其中的eb6b50类似的数值是hash值,用来唯一标识一个提交或其他git的结构,有点类似于指针和地址味道。
一个仓库中可以同时存在多个分支,我们可以基于任何一次提交,新建一个分支,并让之后的提交都沿着新分支流动。
HEAD指针,指向当前正在操作的分支的最新的提交点,你所处分支变化了,HEAD就会跟着变化。
注:分支名指向分支的最新一次提交,HEAD指向当前分支的最新一次提交 ,由于git仓库是使用“链表”的形式管理各个提交的,随意修改链表头的位置,即可回退到某一个版本上(git reset)。
相关指令:
- git branch,创建新分支、查看仓库中有哪些分支、查看当前分支、等等。其实就是创建一个指向某次提交的指针,每次新提交都从分支指向的commit后插入
1.1 git branch name —— 创建分支。
1.2 git branch -a —— 查看所有分支(包括远程仓库)。
1.3 git branch -r —— 查看远程仓库分支。
1.4 git branch –d name —— 删除分支。
1.5 git branch --set-upstream branch-name origin/branch-name
—— 建立本地分支和远程分支之间的连接,这样在某个分支上pull和push就不需要指定目标分支了直接git pull 或git push。一般也就master和dev需要建立两边同步,其他的不需要上传下载的本地分支也就不需要建立连接的 - git checkout,切换分支、创建并切换分支、等,其实就是移动HEAD的指向。
2.1 git checkout -b name —— 创建并切换分支。
2.2 git checkout -b dev origin/dev
—— 从远程仓库克隆下来的仓库在本地只有master分支,其他分支需要创建远程分支的本地分支。
2.3 git checkout name —— 切换分支。 - git switch
3.1 git switch -c dev
—— 也是切换并创建分支,使用switch避免了checkout的两种用途(撤回、切换分支)的混淆 - git merge name —— 合并分支name到当前分支,使用fast forward模式(直接丢弃被合并分支)。
4.1 git merge –no-ff -m “注释” name —— 禁用fast forward合并模式来合并,保留被合并分支。
4.2 如果合并出现冲突,则不会在合并的时候自动提交合并体,而是停下来等用户修改完冲突后提交。可以用git status查看时哪些冲突。冲突的文件中会被类似如下显示文本,手动选择一个然后删去所有文字即可手动合并。
<<<<<<< HEAD:index.html
contact : email.support@github.com
=======
please contact us at support@github.com
>>>>>>> iss53:index.html
- git cherry-pick commit_id
—— 把某次提交的内容合并到本分支上。比如我们把master的bug修复了。但是在修复之前咱们再dev上进行了很多开发是没修复这个bug的基础的,为了修复dev上的bug,可以用这个指令把master上修复bug的commit的内容合并到本分支上,并创建一个新的commit。
利用分支进行开发的工作流程
简单的说就是有一个稳定的master,有一个不稳定的dev,而每个人都有自己的一个独立dev分支取名为自己的名字,然后各自往dev上提交,如果遇到bug了就创建临时分支来debug,有其他的小尝试比如新功能也不要再dev上开发,先额外再创建一个分支在上面开发,在合并到自己的dev上。等dev开发到1.0/2.0版本了,在合并到master上发布。
长期分支
在每次合并新稳定内容到master后,创建一个next或develop分支进行后续的开发。
特性分支
多个分支同时开发,然后简单的三方合并。
远程分支
你clone下来后,自动生成一个origin的远程主机和分支origin/master。同时本地也生成一个分支叫master,指向同一个提交
此后你基于此一直开发,即master一直后移,且别人把新的内容推到远程仓库,但是只要你没和远程仓库交互,这个远程分支就不会移动。
通过git fetch指令可以同步远程仓库数据到本地。
推送本地分支
就是push了
分支的衍合
之前的合并是使用三方合并即分支1和分支2及其共同祖节点(也就是分叉点)三者的合并,然后生成1次新的提交。
以上是合并的样子,而衍合如下所示。以要进行衍合的分支的最后一次提交为基础生成一系列文件补丁,在基底(衍合目标)最后一次提交上,逐个使用补丁。最后生成一个新的合并。
如何看懂diff内容
- git diff
—— 用于查看staging area 和 working area 的文件差别。 - git diff refs/remotes/origin/master
—— 用远程某个分支比较当前工作区 - git diff commit_id filename
—— 比较某个文件的历史版本和工作区的该文件对比。
输出格式
- 开头表示源文件,就是命令指定的那个文件。
+++ 开头的是目标文件。
空格开头的行,是源文件和目标文件中都出现的行。
差异按照差异小结进行组织,每个差异小结的第一行都是定位语句,由@@开头,@@结尾。
- 开头表示源文件,就是命令指定的那个文件。
表示源文件第1行开始的2行和目标文件第1行开始的4行构成差异小结。然后目标文件3、4行多了2句话。空格开头的白色行是- + 两个文件都有的。- 开头的是源文件有的(已经提交的),+是工作空间中的文件的内容。
配置别名
为什么要配置别名因为懒得打字了
git config --global alias.st status
—— 这样st就是status的意思了,以后git status只需要输入git st。
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
—— 好用!
想要删除配置就去看文件的内容删除就好了。
如果是加了--glbal 就是针对当前用户的配置。否则就是针对当前库的。用户配置在用户目录下的.gitconfig。而针对库的配置在.git/config
git的原理
存储结构
blob
git将每个文件存下来。并且通过计算文件的内容SHA-1 哈希值为校验和(40个字节)。如果修改了内容、名字、目录,该值都会变,通过判断校验和是否变了判断文件是否修改。然后以40个字节的头2个字节为目录名,后38个字节16进制为名字保存文件
tree
tree类似于目录。一个tree可以存储tree和blob对象的记录,每一条记录都含有一个指向blob或子树的SHA-1指针,并附带对象权限、类型、文件名等信息。
commit
对象的存储
如何存储一个blob呢?{blob 文件内容长度\0}花括号内容为文件头,后面拼接文件内容行成新内容。然后计算新内容的SHA-1校验和,然后用zlib压缩数据,以SHA-1前2个字节为目录,后38个字节为文件名进行磁盘的写入。所有的git对象都是以这种方式存储的。
综合以上所说:我们知道了Git和所有版本控制软件一样,只能跟踪文本文件(就是代码等)。对于图片、影音,虽然也能进行版本控制,但是只能知道其是否删除和修改,但是修改了哪些内容是不知道的。这类非纯文本(包括word和markdown)是以二进制形式串起来编码的。