Git爬坑记

Posted 千江月09

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Git爬坑记相关的知识,希望对你有一定的参考价值。

Git记录

使用git 也有一段时间了, git的入门级了解也就不再多说, 但平常使用中, 仍然会遇到很多问题, 在此记录一二.

在查资料的过程中, 发现了两个比较好的资料:

特别是第二个, 相当详细的 Git教程, 如果看完的话, 相信对 Git的使用理解已经基本不是问题了.

常用Git命令清单

Git 分支 - 何谓分支

Git基础命令

git config --global user.name "myname"
git config --global user.email "myemail"

个人觉得, 这两项配置的是 每次推送时留下的个人信息, 就相当于 注册账号时的个人信息一样, 别人可以通过这个, 区分, 或联系你, 但至于 email 是否有效, 仍未可知.

新建git仓库, 到对应目录下, 有很多次直接复制路劲过来, 是错误的, 因为 linux 下, 分隔符为 ‘/‘,而非windows下的 ‘\‘.

cd C:/xx/xx
git init;
git status; #检查本地 git 状态

git add: 需要先 add 到暂存区, 然后才能使用 commit进行提交, 在 eclipse里面的操作就是, add to index (对于新建文件而言) , 然后commit, 在commit的时候, 必须要有 commit 信息, 否则无法提交;

git add file; #多个文件之间以 空格 隔开即可 add . 是当前目录所有文件

git rm [file1] [file2]; #删除工作区文件,并将删除放入 暂存区;

git rm --cached [file]; #停止追踪指定文件,但该文件会保留在工作区;

git commit -m "git message"; #输入提交信息即可;

git commit [file] [file1] -m [message] #提交指定文件;

--如果不用Git -a 的话, 必须先 add 后commit;
git commit -a; #提交工作区自上次commit之后的变化,直接到仓库区;
git commit -a -m "输入提交信息";

git commit -v; #提交时显示diff 信息;

git reflog; #查看 git 记录

git reset --hard "reflog header"; # 每次记录都有一个 header 码, 输入对应的编码, 则 回退到, 对应的位置;

Git分支, 不得不说, 分支很强大, 也很有意思

git branch; #查看所有分支

git branch -r; #所有远程分支

git branch -a; #远程及本地分支

git branch [branch-name] #新建一个分支,但依然停留在当前分支

git checkout -b [branch]; #新建一个分支,并切换到该分支

git branch [branch] [commit]; #在指定的 commit处,新建一个分支;

git checkout [branch-name]; #切换到指定分支,并更新工作区

git merge [branch]; #合并指定分支到当前分支

git branch -d [branch-name] 删除分支;

git push origin --delete [branch-name];
git branch -dr [remote/branch]; #删除远程分支

Git 信息查看

git log; #查看当前分支版本历史

git log --stat; #显示commit历史,以及每次commit发生变更的文件

git log -S [keyword]; #搜索提交历史,根据关键词

git log --follow [file]; # 显示某个文件的版本历史,包括文件改名
git whatchanged [file];

git shortlog -sn; # 显示所有提交过的用户,按提交次数排序

Git 远程

对于部分 需要关闭 SSL验证;

git clone [url]; #从远程拉代码;
#http://username:[email protected]; 通过这种方式验证用户名和密码;

git remote add [shortname] [url] #增加一个新的远程仓库,并命名

git remote show [remote] #显示某个远程仓库的信息

git remote -v; #显示所有远程仓库

git fetch [remote]; #下载远程仓库的所有变动, 更新本地库, 但不更新工作拷贝;

#更新指定文件(待验证)
git fetch [remote];
git checkout origin/master [file]

git pull [remote] [branch]; # 取回远程仓库的变化,并与本地分支合并

git push [remote] [branch]; # 上传本地指定分支到远程仓库

git push [remote] --force; # 强行推送当前分支到远程仓库,即使有冲突

git push [remote] --all; # 推送所有分支到远程仓库

Git撤销

git checkout [file]; # 恢复暂存区的指定文件到工作区

git checkout [commit] [file]; #恢复某个commit的指定文件到暂存区和工作区

git checkout .;  #恢复暂存区的所有文件到工作区

git reset [file]; # 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变

git reset --hard; #重置暂存区与工作区,与上一次commit保持一致

git reset [commit]; #重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变

git reset --hard [commit]; #重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致

 git reset --keep [commit] #重置当前HEAD为指定commit,但保持暂存区和工作区不变

 git stash; #暂时将未提交的变化移除,稍后再移入
 git stash pop; #应该指的是移入

 git revert [commit]; 新建一个commit,用来撤销指定commit,后者的所有变化都将被前者抵消,并且应用到当前分支

 # 生成一个可供发布的压缩包
 $ git archive

Git使用

Git基础知识

在基础的命令了解之后, 打算对 git 做一个更深入的了解, 形成更清晰的认知;

至于参考资料,则是官方文档: 起步-Git-基础

在git中, 首先应该提到的是几个比较基础的概念:

文件的三种状态: 已提交, 已修改, 已暂存;

Git目录:

每个项目都有一个 Git 目录(译注:如果 git clone 出来的话,就是其中 .git 的目录;如果 git clone --bare 的话,新建的目录本身就是 Git 目录。),它是 Git 用来保存元数据和对象数据库的地方。

该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。

Git的工作目录:

从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。

文件的修改, 删除, 添加等操作都是在这进行的, 在工作目录进行的操作, 如果没有提交的话, 则文件是处于 已修改状态的.

不难看出, 在 Git的工作目录中, 文件存在两种状态, 已跟踪, 未跟踪, 在已跟踪中 又区分为, 已修改 和 已暂存 两种状态;

Git的暂存区域:

只不过是个简单的文件,一般都放在 Git 目录中。在暂存区域中保存 把已修改的文件放在下次提交时要保存的清单中。

Git的工作流程如下:

  1. 在工作目录中修改文件
  2. 对修改后的文件进行快照, 然后储存到暂存区域
  3. 提交更新, 将保存在暂存区域快照永久储存在Git目录中

Git初入

  1. Git配置

    git config --system #/etc/gitconfig 文件:系统中对所有用户都普遍适用的配置
    
    git config --global; #~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。
    
    git config; #.git/config 文件:这里的配置仅仅针对当前项目有效;每一个级别的配置都会覆盖上层的相同配置
    
    git config --list; #查看已有的配置
    
    git config user.name; #查看特定配置
  2. Git仓库初始化

    #对现有项目使用 Git管理
    
    git init;
    
    git clone git://github.com/schacon/grit.git; #克隆远程仓库, 同时目录名为 grit;
    
    git clone git://github.com/schacon/grit.git mygrit; #可以通过这种方式重命名目录;
    
    git add readme; #使用add 来跟踪一个文件; #git add 对于未曾跟踪的文件进行跟踪, 对于已跟踪的文件 放入暂存区; 对于合并时 冲突的文件 还能将 文件标记为 已解决等;
    
    #最好在项目一开始的时候就配置好 .gitignore 文件;
    
    #所有空行或者以注释符号 # 开头的行都会被 Git 忽略。
    
    #可以使用标准的 glob 模式匹配。
    
    #匹配模式最后跟反斜杠(/)说明要忽略的是目录。 /在最前面 表示根目录
    
    #要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

    所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。

    星号(*)匹配零个或多个任意字符;

    [abc]匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);

    问号(?)只匹配一个任意字符;

    如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。

    # 此为注释 – 将被 Git 忽略
    # 忽略所有 .a 结尾的文件
    *.a
    # 但 lib.a 除外
    !lib.a
    # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
    /TODO
    # 忽略 build/ 目录下的所有文件
    build/
    # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
    doc/*.txt
    # 忽略 doc/ 目录下所有扩展名为 txt 的文件
    doc/**/*.txt  # **/ 通配符在 1.82以上版本可以使用;
  3. Git改动查看:

    git diff; #仅显示还没有暂存起来的改动
    
    git diff --staged; #已经暂存起来的文件和上次提交时的快照之间的差异
  4. Git跳过使用暂存区:

    git commit -a [-m] [file]; 
  5. Git 移除:
    #在删除文件之后, 通过 git rm 移除文件, 以后文件就不会进入版本管理了.
    git rm grit.gemspec; #如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f

    #另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。
    
    git rm --cached readme.txt; 可以使用 glob模式匹配文件名;
  6. Git 重命名文件:

    git mv file_from file_to;
    
    #有时候用其他工具批处理改名的话,要记得在提交前删除老的文件名,再添加新的文件名。
  7. Git 历史/记录

    git log; #可以看到比较详细的信息;
    
    git -p; #可以看到每次提交更新的内容差异
    
    git -p -2; #仅看最近两次的更新;
    
    git log -p -1 --word-diff; #进行单词层面的文件对比;新增加的单词被 {+ +} 括起来,被删除的单词被 [- -] 括起来。
    
    git log --stat; #   仅显示简要的增改行数统计

    除此之外, git log的用法还有多种;

    https://git-scm.com/book/zh/v1/Git-基础-查看提交历史

  8. Git的撤销操作

    git commit --amend;

    可以通过这个命令更改上次的操作, 如果上次提交完没有更改, 可以通过 git commit --amend -m 更改上次提交注释, 否则的话, 将暂存区的 与 上次提交合并;

    git reset HEAD [file]; #可以取消已暂存的所有文件/指定文件;
    
    git checkout -- [file]; #撤销工作目录下文件的更改.
  9. Git远程仓库使用

    git remote [-v]; #查看当前配置有哪些远程仓库[远程仓库地址]
    
    git remote add [shortname] [url]; #添加一个新的远程仓库;
    
    git fetch [remote-name]; #通过这个命令抓取远程仓库有的, 但本地仓库没有的信息;
    
    git pull; #将远程仓库代码更新到本地仓库 且和 工作目录下;

    fetch 命令, 类似于 pull功能, 但并不会自动和 当前的工作目录合并, 需要手工合并, 可以通过这点来实现, 指定文件的 更新;

    git push [remote-name] [url];

    在push的时候, 有一个需要注意的地方, 首先需要在 服务器上有写的权限, 其次同一时刻没有其他人在推送数据, 这条命令才会执行; 如果在你推送之前, 已经有其他人在同一分支推送了数据, 就必须先把他们的更新抓取到本地,合并到自己的项目中,然后才可以再次推送。

    git remote show [remote-name]; #查看远程仓库详细信息;
    
    $ git remote show origin
    * remote origin
    URL: [email protected]:defunkt/github.git
    Remote branch merged with ‘git pull‘ while on branch issues
        issues
    Remote branch merged with ‘git pull‘ while on branch master
        master
    New remote branches (next fetch will store in remotes/origin)
        caching
    Stale tracking branches (use ‘git remote prune‘)
        libwalker
        walker2
    Tracked remote branches
        acl
        apiv2
        dashboard2
        issues
        master
        postgres
    Local branch pushed with ‘git push‘
        master:master
    
    #它告诉我们,运行 git push 时缺省推送的分支是什么(译注:最后两行)。
    #它还显示了有哪些远端分支还没有同步到本地(译注:第六行的 caching 分支).
    #哪些已同步到本地的远端分支在远端服务器上已被删除(译注:Stale tracking branches 下面的两个分支)
    #以及运行 git pull 时将自动合并哪些分支(译注:前四行中列出的 issues 和 master 分支)。

    Git 远程仓库重命名:git remote rename [oldname] [newname];

    Git 远程仓库删除: git remote rm [remote-name];

    git自动命令补全: 自动命令补全

Git分支

Git的分支理解:

在 每一个时刻都存在着无限种可能, 一个不经意的念头, 引领走向截然不同的世界, 一个不经意的巧合, 在时间的节点上 创建出 另一条分支, 另一条时间线, 通向不同的未来.

我们通过 Git branch [branch-name]创建另一条分支, 并可以在这条分支上自由的做任何你想做的事情, 我们是造物主, 因此可以对当前的 分支画上一个 休止符, 转而通过 Git checkout [branch-name] 穿梭到另一条分支上, 因为是两条互不干扰的时间线, 因此, 无论我们穿梭到 哪一个节点, 看到的永远是当时 那个 暂停的画面.

肆意在两条甚至无数条时间线不停穿梭, 而不会相互影响无疑是一种美妙的体验, 但如果想要在穿梭的过程中不迷失, 就需要一个恒定的标识 HEAD, 永远指向当前分支;

如果在新建一条分支的同时 想要切换到对应分支 , 则需要:

git checkout -b [branch-name];

如果想将两条分支合并, 则:

git merge [branch-name]; #指的是将 分支 合并入当前分支;

如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移,因为这种单线的历史分支不存在任何需要解决的分歧,所以这种合并过程可以称为快进(Fast forward)。

对待非上述情况, 会找到共同的祖先节点进行合并.

但有时候为了版本演进的清晰起见会用:

git merge --no-ff feature-x;

merge 命令,它会把两个分支最新的快照 以及二者最新的共同祖先进行三方合并,合并的结果是产生一个新的提交对象

git branch -d [branch-name]; #删除对应分支;

在分支合并的过程中, 难免会出现相互冲突的文件, 对待这样的情况, 只有身为创建者的你, 可以解决这个问题, 将文件找出来.

通过: git status;任何包含未解决冲突的文件都会以未合并(unmerged)的状态列出。

修改成你想要的结果, 然后再次 add 以告诉 git 冲突已经被解决了.

Git 分支管理策略参考:

Git分支管理策略

Git的分支管理

随着项目不断开发, 分支难免会越来越多, 然而这其中可能有很大一部分, 你再也不会用到;

git branch --merged; [--no-merged]; #筛选出和当前分支已合并 或 未合并的分支; 通过这种方式,然后将 已合并的分支删除掉;

在删除掉未合并的分支时, 会报错, 因为会丢失已修改的数据, 如果仍然要强制性删除的话, 可以通过 D 来进行强制删除;

但必须记住的是:

以上分支均为: 本地分支;

Git远程分支

Git的远程分支 仍然是一种分支, 不过比较特殊; 当我们采取 git clone 的方式从远程获取到 项目的时候, 默认创建 origin master(分别指代[remote-name][branch-name]);

此时在 Git目录中保存有两个分支:

origin master 指向 clone 时 远程仓库的 master分支的当前位置;

master 指向本地仓库的分支 位置; 本地 工作目录的更新 会使得 master 向后移动. 仅有在 进行 fetch 或者 pull 操作的时候, 会将远程仓库的最新master 位置更新下来, 同时 fetch操作会更新 本地 Git目录(但不会更新工作目录);

而我们可以通过 git remote add [remote-name] [url] 将指定路径的远程仓库 变为 当前本地 Git的 远程分支;

推送本地分支, 如果要选择某个分支进行推送:

git push --set-upstream origin readme-edit; #对于自己创建的分支, 将分支推送到 仓库;

git push origin serverfix; #将分支推送到远程分支

git push origin [local-branch-name]:[自定义远程分支名称];#也可以通过这种方式 在远程仓库创建分支;

git fetch origin/[远程 特定分支名称, 非默认分支]; #通过这种方式更新本地 Git目录;

对于一个全新的远程分支;

git remote add origin [url];

git fetch origin;

git checkout .; #将暂存区的文件 同步到工作区;

#或者

git checkout -b serverfix origin/serverfix; #将远程分支合并到本地;

#这会切换到新建的 serverfix 本地分支,其内容同远程分支 origin/serverfix 一致,这样你就可以在里面继续开发了。

在克隆仓库时,Git 通常会自动创建一个名为 master 的分支来跟踪 origin/master。这正是 git push 和 git pull 一开始就能正常工作的原因。

当不再需要某个远程分支(而非远程仓库):删除远程分支

git push [远程名]  :[分支名];

git push origin [local-branch-name]:[自定义远程分支名称];

对比下来不难发现, 第一句的意思是 提取空白 然后把它变成远程分支;

Git分支-分支变基

对应的操作是:

git rebase [branch-name];

merge 命令,它会把两个分支最新的快照以及二者最新的共同祖先进行三方合并,合并的结果是产生一个新的提交对象。

rebase: 回到两个分支最近的共同祖先,根据当前分支(也就是要进行变基的分支 branch-name) 后续的历次提交对象, 生成一系列文件补丁,然后以基底分支(也就是主干分支 master)最后一个提交对象为新的出发点,逐个应用之前准备好的补丁文件,最后会生成一个新的合并提交对象, 从而改写 branch-name 的提交历史,使它成为 master 分支的直接下游.

简单的来说: 就是 改写 master分支的提交历史; 在这个基础上, 同时可以修改 冲突文件, 使得合并后不冲突, 在 rebase 之后, 再 进行 merge操作即可.

特别有趣的一点是:

rebase 不一定非得根据 分化之前的分支来进行操作;举个例子如下:

(个人在操作过程中发现与官方文档有所区别, 在操作过程中, 需要时刻关注当前分支)

#当前在本地中只有 master 分支; 创建并切换到 newbranch分支;
git checkout -b newbranch;

#在文档中做一些修改之后, 提交操作;
git commit -a -m ‘new branch 提交修改‘;

#在当前分支节点上再创建新的分支,并切换
git checkout -b newbranch1;

#在newbranch1分支上做出两次修改, 并分别提交;
git add.;
git commit -m ‘添加testrebase.txt文件‘;
git commit -a -m ‘修改 testrebase.txt 文件‘;

#切换到 newbranch 分支做出两次修改, 并分别提交;
git checkout newbranch;
git add .;
git commit -m ‘添加 test_rabase_newbranch.txt文件‘;
git commit -a -m ‘修改 test_rebase_newbranch.txt 文件‘;

#进行rebase 操作;
git rebase --onto master newbranch newbranch1;

#再切换到 master分支查看 操作记录;
git checkout master;
git merge newbranch1;
git log;

#以下是操作记录中的 commit 信息
#修改 testrebase.txt文件
# 添加 testrebase.txt文件
#new master 1

不难发现,在 master 的操作记录中, 并没有 ‘new branch 提交修改‘ 这次的操作记录;

取出 newbranch1 分支,找出 newbranch1 分支和 newbranch 分支的共同祖先之后的变化,然后把它们在 master 上重演一遍;

也就是 在 git commit -a -m ‘new branch 提交修改‘; 操作之后的修改变化;

如果我们再进行的是:

git rebase --onto master newbranch1 newbranch;
git checkout master;
git merge newbranch1;
git log;

#记录
#修改 test_rebase_newbranch.txt 文件
#添加 test_rabase_newbranch.txt文件
#new branch 提交修改

因为 newbranch1 是在 newbranch 上再次新建出来的分支, 而 newbranch 则与master 是同源的;


一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行变基操作。

至此Git 各种操作 告一段落; 也能进行基本的使用, 如果出现问题在网上查找答案, 不至于知其然而不知其所以然;

以上是关于Git爬坑记的主要内容,如果未能解决你的问题,请参考以下文章

单片机爬坑记-02-资源紧缺

vue-router爬坑记

单片机爬坑记-03-编译环境

webpack 爬坑记

微信小程序爬坑记

redis 从库数据同步失败——爬坑记