商汇粹外网资源平台

搜索
查看: 2125|回复: 4

如何学习好 Git ?

[复制链接]

该用户从未签到

4

主题

15

帖子

59

积分

注册会员

Rank: 2

积分
59
发表于 2022-9-27 11:03:44 | 显示全部楼层 |阅读模式
分享一篇牛客大佬 Guanngxu 的 Git 入门进阶及常用命令_技术交流_牛客网
大多数人在学校时候对版本控制器的接触都很少甚至没有接触,所以自己整理了在工作中常用的一些 git 知识,这篇文章的内容差不多可以解决 95% 以上你在使用 git 时遇到的问题,当然如果你要自己搭建一个服务器什么的那本文的内容肯定严重偏浅,如果你只是想查看 Git 常用命令可以选择直接到文章底部「Git 常用命令」阅读,文章大部分内容是 Git 进阶知识,均是自己的读书笔记,如果还想在此基础上再上一层楼,那可以直接看 Pro Git book。
Git 历史

版本控制器是一种记录一个或若干文件内容变化,以便将来查阅特定版本的修订情况。也就是说,版本控制器记录了一个可供考证的历史数据,通过该数据可以知道文件是怎么一步一步发展到今天这个样子的。
最初 Linux 项目使用 BitKeeper 来管理和维护代码,但是到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了免费使用 BitKeeper 的权力。那 Linux 开源社区的解决方案就是自己搞一个版本控制器,所以就有了 Git。
简单说就是 Linus 被逼的去开发了这一款叫做 Git 的版本控制器,因为 Linus 本身就是内核专家与文件专家,所以 Git 也就自然而然具备了非凡的存储能力与性能。
安装

关于如何安装 git 可以查看 Pro Git book,安装完成后需要进行一些必要的配置,比如用户信息、文本编辑器、差异分析工具等等,我们可以通过git config --list来查看配置信息。比如我们要配置用户和邮箱,就可以像下面这样输入命令。
$ git config --global user.name "John Doe"$ git config --global user.email johndoe@example.com
Git 原理

Git 和大多数版本控制器有一个重要的区别,就是它直接记录快照,而非差异比较,其它大部分系统以文件变更列表的方式存储信息,而 Git 则存储每个文件与初始版本的差异。换句话说,只要你的文件有改动,那么 Git 就会将该文件复制一份,正因为 Git 的这个特性,所以 Git 仓库很容易就变得非常大;为了高效,如果文件没有修改,那么 Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。Git 对待数据更像是一个快照流。
Git 有三个区,分别为:仓库、工作目录、暂存区。基本的 Git 流程为:1)在工作目录中修改文件;2)暂存文件,将文件的快照放入暂存区域;3)提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。那么相应的 Git 就有三种状态:已提交(committed)、已修改(modified)和已暂存(staged),你的文件可能处于其中之一。

Git 基础

工作目录中的文件不外乎处于两种状态:已跟踪或未跟踪。已跟踪是指那些纳入了版本控制的文件,在上一次快照中有它们的记录;工作目录中除了已跟踪文件以外的所有文件都属于未跟踪文件,们既不存在于上次快照的记录中,也没有放入暂存区。

查看文件状态

如果需要查看哪些文件处于什么状态,可以使用git status命令,这个命令显示的信息十分详细,如果你喜欢简洁一点的信息,那么可以在其后添加一个-s,其报告格式类似于下面这样。
$ git status -s M READMEMM RakefileA  lib/git.rbM  lib/simplegit.rb?? LICENSE.txt
??表示新添加的未跟踪文件;修改过的文件前面有M标记,右边的表示还没有放入暂存区,左边的表示已经放入暂存区了。当然你可能不希望每个文件都出现在未跟踪列表中,比如编译过程临时创建的文件、日志文件等等,所以可以通过创建一个名为.gitignore的文件,列出要忽略的文件模式,它支持标准的glob模式匹配(shell 所使用的简化了的正则表达式),在 gitignore 中有一个十分详细的针对数十种项目及语言的.gitignore文件列表。
git status对于具体修改显示的过于模糊,如果想查看具体修改了什么地方,可以使用git diff命令,比如git diff README.md。需要注意的是git diff本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动,如果需要查看已经暂存起来的变化,则要加上--staged或者--cached,比如git diff --cached README.md。
删除文件

当然我们不可避免的需要删除某个文件,如果你仅仅是简单的从工作目录中手工删除文件,那它并没有真正的从 Git 中删除,Git 会将这次删除识别为一次改动。更好的方式是使用git rm命令来完成删除文件的工作,比如git rm README.md就会从已跟踪文件中删除,并且连带从工作目录中删除指定文件。
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项-f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删还没有添加到快照的数据,这样的数据不能被 Git 恢复。
另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。这时就需要使用--cached选项了,比如git rm --cached README。
查看历史

我们或许因为某种原因需要回顾一下提交历史,这时git log就派上用场了,默认不用任何参数的话,git log会按提交时间列出所有的更新,最近的更新排在最上面,这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。
git log提供的选项很多,更详细的内容可以查看 Git 基础 - 查看提交历史。除了不带选项的命令,我个人更常用的命令还有另外两个,分别为:git log --pretty=oneline它将每个提交放在一行显示,在查看的提交数很大时非常有用;git log --graph或者git log --pretty=oneline --graph用于显示 ASCII 图形表示的分支合并历史。
撤销操作

在任何一个阶段我们都可能有想要撤销的操作,我们只需要掌握几个基本的撤销操作就能够应对日常的工作了。
第一种情况:取消上一次提交。有时候当我们提交完之后才发现漏掉了几个文件没有添加,或者是提交信息写错了,此时可以使用带--amend选项的提交命令尝试重新提交,即git commit --amend。这个命令会将暂存区的文件全部提交,如果自上次提交以来你还没一做任何修改(比如,在上次提交后马上执行了此命令),那么快照将会保持不变,而所修改的只是提交信息。
第二种情况:取消暂存的文件。假设你修改了两个文件并且想要将它们作为两次独立提交,但是却不小心输入了git add *暂存了它们两个,如何取消其中一个暂存呢?其实在运行git status时已经给出提示了。
$ git statusOn branch masterChanges to be committed:  (use "git reset HEAD <file>..." to unstage)    renamed:    README.md -> README    modified:   CONTRIBUTING.md
所以如果我们想要取消CONTRIBUTING.md的暂存,那么就可以用git reset HEAD CONTRIBUTING.md命令来完成。
第三种情况:撤销对文件的修改。有时候我们可能并不想保留对某个(若干)文件的修改,git status也给出了详细的提示,告诉我们如何将文件还原成上次提交时的样子,即git checkout -- <file>,比如输入命令git checkout -- CONTRIBUTING.md,就会将CONTRIBUTING.md重置到上一次提交时的样子。
需要注意的是git checkout -- <file>是一个比较危险的命令,因为它仅仅是拷贝了另一个文件来覆盖当前文件,所以你对那个文件的所有修改都会消失,而且不可恢复。
远程仓库

前面我们都是在讲本地操作,远程仓库的使用是必不可少的技能。可以使用git remote命令查看每一个远程服务器的简写,对于已经克隆的仓库,它至少会包含一个origin,这是 Git 给克隆仓库服务器取的默认名字,它和其它服务器并没有什么区别,只是很少人会去修改这个默认名字而已。
如果想要给一个远程仓库重新取一个简写名,那么可以运行git remote rename来完成,比如git remote rename pb paul就是将pb重命名为paul。值得注意的是这样同样也会修改你的远程分支名字,那些过去引用pb/master的现在全引用paul/master。
当想要将自己的成果分享给他人时,就需要将其推送到上游,使用git push [remote-name] [branch-name]即可,比如你想要将master分支推送到origin服务器时,就可以运行git push origin master。
除了分享自己的成果,我们也需要获取他人的成果,即从仓库拉取自己没有的信息,比如git fetch origin,需要注意的是git fetch命令会将数据拉取到你的本地仓库,但它并不会自动合并或修改你当前的工作,所以你还需要git merge来合并分支,实际上有一个git pull命令可以帮我们把这两个步骤都做了,你可以简单的将git pull理解为git fetch后面紧接着一个git merge。
分支管理

Git 的分支模型是它的必杀技特性,它处理分支的方式是难以置信的轻量,创建分支几乎是在一瞬间完成,而且在不同分支间的切换也非常的便捷,要理解 Git 的分支,我们必须要再次回顾 Git 是如何保存数据的。
下图是我们的一个工作流,可以看到所谓的分支实际上就是一个可以移动的指针而已,master、v1.0都仅仅是一个指针,而创建分支、切换分支等操作也都只是对指针的操作,因此就不奇怪为什么 Git 这么快了。

那么 Git 又是如何知道当前在哪一个分支上呢?它仅仅是用了一个名为HEAD的特殊指针,你可以将HEAD想象为当前分支的别名,HEAD指向哪个分支,就表示当前处于哪个分支。
分支创建与切换

我们可以使用git branch [branch-name]来创建一个新的分支,比如git branch testing;如果使用不带选项的git branch,那么它会列出当前所有的分支,这里需要注意的是master分支也不是特殊分支,它是运行git init时自动创建的默认分支,因为大家都懒得去改它,所以它就好像变得特殊了一样。
git branch [branch-name]只是创建了一个新分支,并不会切换到这个分支上面去,分支的切换说白了就是移动HEAD指针,我们只需要使用git checkout testing就可以切换到testing分支上去了。
当然我们可以使用git checkout -b [branch-name]来创建一个分支并同时切换到这个分支,把这个命令与git commit -a -m来对比,你就会发现它们的类似之处。
更多名企笔试真题解析、面试经验交流、招聘信息内推,尽在牛客!
求职之前,先上牛客!快快下载拿offer!
牛客APP下载_C++Java前端经典笔试面试题库_牛客网
分支的合并与删除

当我们零时在一个新分支上解决了问题后,需要将其合并到master分支,只需要切换到master再运行git merge命令即可,Git 会自动找到这两个分支的共同祖先,然后做一个简单的三方合并。
当然理想情况下是直接合并成功,但是不免会遇到合并冲突的情况,一旦遇到冲突了,Git 会像下面这样来标记冲突内容,你需要做的是选择由=======分割的令部分的其中一个或者自行合并,当<<<<<<<,=======,和>>>>>>>这些行被完全删除了,你需要对每个文件使用git add将其标记为冲突已解决。
<<<<<<< HEAD:index.html<div id="footer">contact : email.support@github.com</div>=======<div id="footer"> please contact us at support@github.com</div>>>>>>>> testing:index.html
当合并完分支后,之前的分支一般就不会再要了,这时你可以运行git branch -d [branch-name]来删除指定分支,比如使用git branch -d testing来删除testing分支。
远程分支

远程分支以(remote)/(branch)的形式来命名。如下图所示,如果你克隆一个仓库下来,那么这个仓库除了会有一个本地的分支指针,还会有一个远程分支指针。如果你在本地的master分支做了一些工作,但是你并没有与origin服务器连接,那么你的origin/master指针就不会移动。

在这之前我们已经讲过通过推送分享自己的成果,在运行git push origin master命令时,Git 会自动的将master分支名字展开为refs/heads/master:refs/heads/master,即意味着推送本地的master分支来更新远程仓库上的master分支,所以你也可以运行git push origin master:testing来做类似的事,如果远程仓库没有testing分***它会自己创建一个新的testing分支。
我们肯定需要创建一个跟踪远程仓库的其它分支,最简单的就是运行git checkout -b [new-branch] [remote-name]/[branch],该命令会以远端[branch]分支的内容来创建本地的[new-branch]分支,Git 也对该命令做了一个简化,git checkout --track [remote-name]/[branch],该命令就会在本地创建一个[branch]分支用于跟踪远端的[branch]分支。
当然,我们还需要了解一个删除远程分支的命令git push origin --delete [branch],需要注意的是这个命令基本上只是从服务器上移除这个指针。 Git 服务器通常会保留数据一段时间直到垃圾回收运行,所以如果不小心删除掉了,通常是很容易恢复的。
Git 常用命令

挑了一些比较重要 Git 命令,我把个人常用的命令使用代码块标记出来了。

<hr>
如果觉得有用,就给牛妹点个赞吧~ღ( ´・ᴗ・` )比心
回复

使用道具 举报

该用户从未签到

4

主题

14

帖子

46

积分

新手上路

Rank: 1

积分
46
发表于 2022-9-27 11:20:24 | 显示全部楼层
把下面这本书的前三章好好读读,基本就足够了,前三章主要是基础,但却是地基,都是些非常重要的内容。

后面的内容大部分都不用看了,如果还没有学会使用,看也看不懂。不过,你如果想了解 github  的使用,github 那部分可以读读。有部分讲暂存和重写历史的,可能经常会用到,


那本书后面的内容都是些高级的话题,如果能把后面看完,一些异常情况基本可以自己解决了。
再者,给大家推荐一个网站,一个 git 学习网站,依据你提交的信息,实时展示当前的分支情况。

一个简单的演示效果,如下:








简直是 git 学习的神器是也。
最后一个建议。
初学的话,首先得会用 git,等到一定阶段,仔细了解下它的设计架构。了解下你的每步操作在做什么,对 git 的使用会比较有帮助。
比如,我画的下面这张图:

学会基本操作,理解了架构,再通过前面推荐的辅助学习的网站学习,git 完全不是事啊。
回复

使用道具 举报

该用户从未签到

13

主题

67

帖子

237

积分

中级会员

Rank: 3Rank: 3

积分
237
发表于 2022-9-27 11:37:04 | 显示全部楼层
A List of Git Commands

Git Setup

Create a new Git repository from an existing directory:
git init [directory]
Clone a repository (local or remote via HTTP/SSH):
git clone [repo / URL]
Clone a repository into a specified folder on your local machine:
git clone [repo / URL] [folder]
Git Configuration

Attach an author name to all commits that will appear in the version history:
git config --global user.name "[your_name]"
Attach an email address to all commits by the current user:
git config --global user.email "[email_address]"
Apply Git’s automatic command line coloring which helps you keep track and revise repository changes:
git config --global color.ui auto
Create a shortcut (alias) for a Git command:
git config --global alias.[alias_name] [git_command]

Note: Git requires you to type out the entire command to perform actions. Setting shortcuts for commonly used commands can speed up and simplify development. For example, you can use the alias st for the status command by typing the command: git config --global alias.st status
Set a default text editor:
git config --system core.editor [text_editor]
Open Git’s global configuration file:
git config --global --edit
Managing Files

Show the state of the current directory (list staged, unstaged, and untracked files):
git status
List the commit history of the current branch:
git log
List all commits from all branches:
git log --all
Compare two branches by showing which commits from the first branch are missing from the second branch:
git log [branch1]..[branch2]
Examine the difference between the working directory and the index:
git diff
Explore the difference between the last commit and the index:
get diff --cached
See the difference between the last commit and the working directory:
get diff HEAD
Display the content and metadata of an object (blob, tree, tag or commit):
git show [object]
Git Branches

List all branches in the repository:
git branch
List all remote branches:
git branch -aa
Create a new branch under a specified name:
git branch [branch]
Switch to a branch under a specified name (if it doesn’t exist, a new one will be created):
git checkout [branch]

Note: For a more detailed tutorial on working with Git branches, you can refer to our article on How to Create a New Branch or How to Switch Branches in Git.
Delete a local branch:
git branch -d [branch]
Rename a branch you are currently working in:
git branch -m [new_branch_name]
Merge the specified branch with the current branch:
git merge [branch]
Making Changes

Stage changes for the next commit:
git add [file/directory]
Stage everything in the directory for an initial commit:
git add .
Commit staged snapshots in the version history with a descriptive message included in the command:
git commit -m "[descriptive_message]"
Undoing Changes

Undo changes in a file or directory and create a new commit with the git revert command:
git revert [file/directory]
Unstage a file without overwriting changes:
git reset [file]
Undo any changes introduced after the specified commit:
git reset [commit]
Show untracked files which will be removed when you run git clean (do a dry run):
git clean -n
Remove untracked files:
git clean -f
Rewriting History

Replace the last commit with a combination of the staged changes and the last commit combined:
git commit --amend
Rebase the current branch with the specified base (it can be a branch name, tag, reference to a HEAD, or a commit ID):
git rebase [base]
List changes made to the HEAD of the local repository:
git reflog
Remote Repositories

Create a new connection to a remote repository (give it a name to serve as a shortcut to the URL):
git remote add [name] [URL]
Fetch a branch from a remote repository:
git fetch [remote_repo] [branch]
Fetch a repository and merge it with the local copy:
git pull [remote_repo]
Push a branch to a remote repository with all its commits and objects:
git push [remote_repo] [branch]
cheat sheet

回复

使用道具 举报

该用户从未签到

5

主题

30

帖子

124

积分

注册会员

Rank: 2

积分
124
发表于 2022-9-27 11:53:44 | 显示全部楼层
Git 是程序员学习和工作都离不开发工具,也是非程序员非常喜欢用的文档版本管理工具。学好 Git 是非常有必要的!





先来说说版本控制系统吧。
顾名思义,版本控制系统(Version Control System)是一类用于追踪源代码改动的工具,这些工具可以帮助我们管理代码的历史记录,不仅如此,还可以让协作编码变得轻而易举。
VCS 通过一系列的快照(Snapshots)将某个文件夹以及内容保存起来,每个快照都包含了文件夹的完整状态。同时,VCS 还维护者快照的创建者信息以及其他相关信息。
大家都知道,版本控制系统非常重要!!!!!!即便你只是一个人在编码,它也可以帮助你创建项目的快照、记录每个改动、创建不同的分支等等。如果你参与的是多人协作,它更是一个无价之宝,你不仅可以看到别人对代码的修改,还可以同时解决由于并行开发带来的冲突。
版本控制系统可以轻松地帮助我们解决这些棘手的问题:

  • 当前模块是谁编写的?
  • 这个文件的这一行代码是什么时候被修改的?是谁做出的修改?修改的原因是什么?
  • 最近的 100 个版本中,哪个版本导致单元测试失败了?
版本控制系统有很多,其中最突出的代表就是 Git——关于它诞生的历史,可以参照我之前分享的一篇内容:一次改变世界的代码提交
如果我们从命令行接口开始学习 Git 的话,会感到非常的困惑,很多时候只能死记硬背一些命令行,然后像变魔法一样使用它们,一旦出现问题,就只能先保存一个分支,然后删掉当前项目,重新下载一份新的拷贝。
尽管 Git 的接口有些难懂,但它底层的设计和思想却非常的优雅。难懂的接口只能靠死记硬背,但优雅的底层设计则非常容易理解。我们可以通过一种自底向上的方式来学习 Git,先了解底层的数据模型,再学习它的接口。可以这么说,一旦搞懂了 Git 的数据模型,再学习它的接口并理解这些接口是如何操作数据模型的就非常容易了。
进行版本控制的方法很多,Git 拥有一个精心设计的模型,这使其能够支持版本控制所需的所有特性,比如维护历史记录、支持分支和团队协作。
Git 将顶级目录中的文件和文件夹称作集合,并通过一系列快照来管理历史记录。在 Git 的术语中,文件被称为 blob 对象(数据对象),也就是一组数据。目录则被称为 tree(树),目录中可以包含文件和子目录。
<root> (tree)|+- foo (tree)|  ||  + bar.txt (blob, contents = "hello world")|+- baz.txt (blob, contents = "git is wonderful")
顶层的树(也就是 root) 包含了两个元素,一个名为 foo 的子树(包含了一个 blob 对象“bar.txt”),和一个 blob 对象“baz.txt”。
版本控制系统是如何和快照进行关联的呢?线性历史记录是一种最简单的模型,它包含了一组按照时间顺序线性排列的快照。不过,出于种种原因,Git 没有采用这种模型。
在 Git 中,历史记录是一个由快照组成的有向无环图。“有向无环图”,听起来很高大上,但其实并不难理解。我们只需要知道这代表 Git 中的每个快照都有一系列的父辈,也就是之前的一系列快照。这些快照通常被称为“commit”,看起来好像是下面这样:
o <-- o <-- o <-- o            ^               \              --- o <-- o
o 表示一次 commit,也就是一次快照。箭头指向了当前 commit 的父辈。在第三次 commit 之后,历史记录分叉成了两条独立的分支,这可能是因为要同时开发两个不同的特性,它们之间是相互独立的。开发完成后,这些分支可能会被合并为一个新的 commit,这个新的 commit 会同时包含这些特性,看起来好像是下面这样:
o <-- o <-- o <-- o <---- o            ^            /             \          v              --- o <-- o
Git 中的 commit 是不可改变的。当然了,这并不意味着不能被修改,只不过这种“修改”实际上是创建了一个全新的提交记录。
以伪代码的形式来学习 Git 的数据模型,可能更加通俗易懂。
// 文件是一组数据type blob = array<byte>// 一个包含了文件和子目录的目录type tree = map<string, tree | file>// 每个 commit 都包含了一个父辈,元数据和顶层树type commit = struct {    parent: array<commit> // 父辈    author: string // 作者    message: string // 信息    snapshot: tree // 快照}
Git 中的对象可以是 blob、tree 或者 commit:
type object = blob | tree | commit
Git 在存储数据的时候,所有的对象都会基于它们的安全散列算法进行寻址。
objects = map<string, object>def store(object):    id = sha1(object)    objects[id] = objectdef load(id):    return objects[id]
blob、tree 和 commit 一样,都是对象。当它们引用其他对象时,并没有真正在硬盘上保存这些对象,而是仅仅保存了它们的哈希值作为引用。
还记得之前的例子吗?

root 引用的 foo 和 baz.txt 就像下面这样:
100644 blob 4448adbf7ecd394f42ae135bbeed9676e894af85    baz.txt040000 tree c68d233a33c5c06e0340e4c224f0afca87c8ce87    foo
所有的快照都可以通过它们的哈希值来标记,但 40 位的十六进制字符实在是太难记了,很不方便。针对这个问题,Git 的解决办法是给这些哈希值赋予一个可读的名字,也就是引用(reference),引用是指向 commit 的指针,与对象不同,它是可变的,可以被更新,指向新的 commit。通常,master 引用通常会指向主分支的最新一次 commit。
references = map<string, string>def update_reference(name, id):    references[name] = iddef read_reference(name):    return references[name]def load_reference(name_or_id):    if name_or_id in references:        return load(references[name_or_id])    else:        return load(name_or_id)
这样,Git 就可以使用“master”这样容易被记住的名称来表示历史记录中特定的 commit,而不需要再使用一长串的十六进制字符了。
在 Git 中,当前的位置有一个特殊的索引,它就是“HEAD”。
在硬盘上,Git 仅存储对象和引用,因为其数据模型仅包含这些东西。所有的 git 命令都对应着对 commit 树的操作。
Git 中还包含了一个和数据模型完全不行管的概念,叫做“暂存区”,它运行我们指定下次快照中要包含哪些改动。
原文链接:牛逼的Git!!!!!!!
作者:沉默王二
下面,我们来看一下常用的 git 命令行接口,包含基础、分支与合并、远端操作、撤销和高级操作。
1)基础

  • git help <command>: 获取 git 命令的帮助信息
  • git init: 创建一个新的 git 仓库,其数据会存放在一个名为 .git 的目录下
  • git status: 显示当前的仓库状态
  • git add <filename>: 添加文件到暂存区
  • git commit: 创建一个新的提交
  • git log: 显示历史日志
  • git log --all --graph --decorate: 可视化历史记录(有向无环图)
  • git diff <filename>: 显示与上一次提交之间的差异
  • git diff <revision> <filename>: 显示某个文件两个版本之间的差异
  • git checkout <revision>: 更新 HEAD 和目前的分支
2)分支与合并

  • git branch: 显示分支
  • git branch <name>: 创建分支
  • git checkout -b <name>: 创建分支并切换到该分支
  • git merge <revision>: 合并到当前分支
  • git mergetool: 使用工具来处理合并冲突
3)远端操作

  • git remote: 列出远端
  • git remote add <name> <url>: 添加一个远端
  • git push <remote> <local branch>:<remote branch>: 将对象传送至远端并更新远端引用
  • git branch --set-upstream-to=<remote>/<remote branch>: 创建本地和远端分支的关联关系
  • git fetch: 从远端获取对象/索引
  • git pull: 相当于 git fetch; git merge
  • git clone: 从远端下载仓库
4)撤销

  • git commit --amend: 编辑提交的内容或信息
  • git reset HEAD <file>: 恢复暂存的文件
  • git checkout -- <file>: 丢弃修改
5)高级操作

  • git config: 定制化
  • git clone --shallow: 克隆仓库,但是不包括版本历史信息
  • git add -p: 交互式暂存
  • git blame: 查看最后修改某行的人
  • git stash: 暂时移除工作目录下的修改内容
  • git bisect: 通过二分查找搜索历史记录
  • .gitignore: 指定不追踪的文件
怎么样?这样学 Git 是不是就容易多了?先从跟上理解了 Git 的数据模型,然后在执行命令的时候去思考这些命令是如何操作数目模型的,就会不那么枯燥了
强烈推荐大家阅读一下这份 Pro Git 中文版,作者参与过 Git 的深度开发,可以说是业界经典的一本小册子了,学习 Git 的必备手册

这次分享给大家,获取方式(含download方式):

该死,又是一篇收藏夹吃灰的。Git非常强大,还有很多功能有待大家去发现哦。
我是二哥 @沉默王二

记得点赞关注哟~
回复

使用道具 举报

该用户从未签到

8

主题

33

帖子

105

积分

注册会员

Rank: 2

积分
105
发表于 2022-9-27 12:10:24 | 显示全部楼层
分享一篇文章,你对了解git会很有帮助!

  • 前言
  • Git简介
  • 实用主义
  • 深入探索
  • 总结
  • 参考资料
Git简介

Git 是一种分布式版本控制系统,它可以不受网络连接的限制,加上其它众多优点,目前已经成为程序开发人员做项目版本管理时的首选,非开发人员也可以用 Git 来做自己的文档版本管理工具。
大概是大二的时候开始接触和使用Git,从一开始的零接触到现在的重度依赖,真是感叹 Git 的强大。
Git 的api很多,但其实平时项目中90%的需求都只需要用到几个基本的功能即可,所以本文将从 实用主义 和 深入探索 2个方面去谈谈如何在项目中使用 Git,一般来说,看完 实用主义 这一节就可以开始在项目中动手用。
“说明:本文的操作都是基于 Mac 系统
我这里整理出一份算法pdf,pdf中不仅有刷题大纲、刷题顺序,还有详细图解,每一本pdf发布之后都广受好评先,pdf中攻击30w字详细图解了 100多道力扣上的经典题目,上图:

无论现在要不要学习算法,先去下载看看吧,想进大厂一定需要这个!

实用主义

准备阶段

进入 Git官网 下载合适你的安装包,安装好 Git 后,打开命令行工具,进入工作文件夹(为了便于理解我们在系统桌面上演示),创建一个新的demo文件夹。

进入 Github网站 注册一个账号并登录,进入 我的博客,点击 Clone or download,再点击 Use HTTPS ,复制项目地址 https://github.com/gafish/gafish.github.com.git 备用。
再回到命令行工具,一切就绪,接下来进入本文的重点。
常用操作

所谓实用主义,就是掌握了以下知识就可以玩转 Git,轻松应对90%以上的需求。以下是实用主义型的Git命令列表,先大致看一下

  • git clone
  • git config
  • git branch
  • git checkout
  • git status
  • git add
  • git commit
  • git push
  • git pull
  • git log
  • git tag
接下来,将通过对 我的博客 仓库进行实例操作,讲解如何使用 Git 拉取代码到提交代码的整个流程。
git clone

“从git服务器拉取代码
git clone https://github.com/gafish/gafish.github.com.git
代码下载完成后在当前文件夹中会有一个 gafish.github.com 的目录,通过 cd gafish.github.com 命令进入目录。
git config

“配置开发者用户名和邮箱
git config user.name gafishgit config user.email gafish@qqqq.com
每次代码提交的时候都会生成一条提交记录,其中会包含当前配置的用户名和邮箱。
git branch

“创建、重命名、查看、删除项目分支,通过 Git 做项目开发时,一般都是在开发分支中进行,开发完成后合并分支到主干。
git branch daily/0.0.0
创建一个名为 daily/0.0.0 的日常开发分支,分支名只要不包括特殊字符即可。
git branch -m daily/0.0.0 daily/0.0.1
如果觉得之前的分支名不合适,可以为新建的分支重命名,重命名分支名为 daily/0.0.1
git branch
通过不带参数的branch命令可以查看当前项目分支列表
git branch -d daily/0.0.1
如果分支已经完成使命则可以通过 -d 参数将分支删除,这里为了继续下一步操作,暂不执行删除操作
git checkout

“切换分支
git checkout daily/0.0.1
切换到 daily/0.0.1 分支,后续的操作将在这个分支上进行
git status

“查看文件变动状态
通过任何你喜欢的编辑器对项目中的 README.md 文件做一些改动,保存。
git status
通过 git status 命令可以看到文件当前状态 Changes not staged for commit:(改动文件未提交到暂存区
On branch daily/0.0.1Changes not staged for commit:  (use "git add <file>..." to update what will be committed)  (use "git checkout -- <file>..." to discard changes in working directory)    modified:   README.mdno changes added to commit (use "git add" and/or "git commit -a")
git add

“添加文件变动到暂存区
git add README.md
通过指定文件名 README.md 可以将该文件添加到暂存区,如果想添加所有文件可用 git add . 命令,这时候可通过 git status 看到文件当前状态 Changes to be committed: (文件已提交到暂存区
On branch daily/0.0.1Changes to be committed:  (use "git reset HEAD <file>..." to unstage)    modified:   README.md
git commit

“提交文件变动到版本库
git commit -m '这里写提交原因'
通过 -m 参数可直接在命令行里输入提交描述文本
git push

“将本地的代码改动推送到服务器
git push origin daily/0.0.1
origin 指代的是当前的git服务器地址,这行命令的意思是把 daily/0.0.1 分支推送到服务器,当看到命令行返回如下字符表示推送成功了。
Counting objects: 3, done.Delta compression using up to 8 threads.Compressing objects: 100% (2/2), done.Writing objects: 100% (3/3), 267 bytes | 0 bytes/s, done.Total 3 (delta 1), reused 0 (delta 0)remote: Resolving deltas: 100% (1/1), completed with 1 local objects.To https://github.com/gafish/gafish.github.com.git * [new branch]      daily/0.0.1 -> daily/0.0.1
现在我们回到Github网站的项目首页,点击 Branch:master 下拉按钮,就会看到刚才推送的 daily/00.1 分支了
git pull

“将服务器上的最新代码拉取到本地
git pull origin daily/0.0.1
如果其它项目成员对项目做了改动并推送到服务器,我们需要将最新的改动更新到本地,这里我们来模拟一下这种情况。
进入Github网站的项目首页,再进入 daily/0.0.1 分支,在线对 README.md 文件做一些修改并保存,然后在命令中执行以上命令,它将把刚才在线修改的部分拉取到本地,用编辑器打开 README.md ,你会发现文件已经跟线上的内容同步了。
如果线上代码做了变动,而你本地的代码也有变动,拉取的代码就有可能会跟你本地的改动冲突,一般情况下 Git 会自动处理这种冲突合并,但如果改动的是同一行,那就需要手动来合并代码,编辑文件,保存最新的改动,再通过 git add .和 git commit -m 'xxx' 来提交合并。
git log

“查看版本提交记录
git log
通过以上命令,我们可以查看整个项目的版本提交记录,它里面包含了提交人、日期、提交原因等信息,得到的结果如下:
commit c334730f8dba5096c54c8ac04fdc2b31ede7107aAuthor: gafish <gafish@qqqq.com>Date:   Wed Jan 11 09:44:13 2017 +0800    Update README.mdcommit ba6e3d21fcb1c87a718d2a73cdd11261eb672b2aAuthor: gafish <gafish@qqqq.com>Date:   Wed Jan 11 09:31:33 2017 +0800    test.....
提交记录可能会非常多,按 J 键往下翻,按 K 键往上翻,按 Q 键退出查看
git tag

“为项目标记里程碑
git tag publish/0.0.1git push origin publish/0.0.1
当我们完成某个功能需求准备发布上线时,应该将此次完整的项目代码做个标记,并将这个标记好的版本发布到线上,这里我们以 publish/0.0.1 为标记名并发布,当看到命令行返回如下内容则表示发布成功了
Total 0 (delta 0), reused 0 (delta 0)To https://github.com/gafish/gafish.github.com.git * [new tag]         publish/0.0.1 -> publish/0.0.1
.gitignore

“设置哪些内容不需要推送到服务器,这是一个配置文件
touch .gitignore
.gitignore 不是 Git 命令,而在项目中的一个文件,通过设置 .gitignore 的内容告诉 Git 哪些文件应该被忽略不需要推送到服务器,通过以上命令可以创建一个 .gitignore 文件,并在编辑器中打开文件,每一行代表一个要忽略的文件或目录,如:
demo.htmlbuild/
以上内容的意思是 Git 将忽略 demo.html 文件 和 build/ 目录,这些内容不会被推送到服务器上
小结

通过掌握以上这些基本命令就可以在项目中开始用起来了,如果追求实用,那关于 Git 的学习就可以到此结束了,偶尔遇到的问题也基本上通过 Google 也能找到答案,如果想深入探索 Git 的高阶功能,那就继续往下看 深入探索 部分。
深入探索

基本概念

工作区(Working Directory

就是你在电脑里能看到的目录,比如上文中的 gafish.github.com 文件夹就是一个工作区



本地版本库(Local Repository

工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。

暂存区(stage

本地版本库里存了很多东西,其中最重要的就是称为 stage(或者叫index)的暂存区,还有 Git 为我们自动创建的第一个分支 master,以及指向 master 的一个指针叫 HEAD。
远程版本库(Remote Repository

一般指的是 Git 服务器上所对应的仓库,本文的示例所在的github仓库就是一个远程版本库



以上概念之间的关系

工作区、暂存区、本地版本库、远程版本库之间几个常用的 Git 操作流程如下图所示:

分支(Branch

分支是为了将修改记录的整个流程分开存储,让分开的分支不受其它分支的影响,所以在同一个数据库里可以同时进行多个不同的修改

主分支(Master

前面提到过 master 是 Git 为我们自动创建的第一个分支,也叫主分支,其它分支开发完成后都要合并到 master



标签(Tag

标签是用于标记特定的点或提交的历史,通常会用来标记发布版本的名称或版本号(如:publish/0.0.1),虽然标签看起来有点像分支,但打上标签的提交是固定的,不能随意的改动,参见上图中的1.0 / 2.0 / 3.0
HEAD

HEAD 指向的就是当前分支的最新提交

“以上概念了解的差不多,那就可以继续往下看,下面将以具体的操作类型来讲解 Git 的高阶用法
操作文件

git add

“添加文件到暂存区
git add -i
通过此命令将打开交互式子命令系统,你将看到如下子命令
***Commands***  1: status      2: update      3: revert      4: add untracked  5: patch      6: diff      7: quit      8: help
通过输入序列号或首字母可以选择相应的功能,具体的功能解释如下:

  • status:功能上和 git add -i 相似,没什么鸟用
  • update:详见下方 git add -u
  • revert:把已经添加到暂存区的文件从暂存区剔除,其操作方式和 update类似
  • add untracked:可以把新增的文件添加到暂存区,其操作方式和 update 类似
  • patch:详见下方 git add -p
  • diff:比较暂存区文件和本地版本库的差异,其操作方式和 update 类似
  • quit:退出 git add -i 命令系统
  • help:查看帮助信息
git add -p
直接进入交互命令中最有用的 patch 模式
这是交互命令中最有用的模式,其操作方式和 update 类似,选择后 Git 会显示这些文件的当前内容与本地版本库中的差异,然后您可以自己决定是否添加这些修改到暂存区,在命令行 Stage deletion [y,n,q,a,d,/,?]? 后输入 y,n,q,a,d,/,? 其中一项选择操作方式,具体功能解释如下:

  • y:接受修改
  • n:忽略修改
  • q:退出当前命令
  • a:添加修改
  • d:放弃修改
  • /:通过正则表达式匹配修改内容
  • ?:查看帮助信息
git add -u
直接进入交互命令中的 update 模式
它会先列出工作区 修改 或 删除 的文件列表,新增 的文件不会被显示,在命令行 Update>> 后输入相应的列表序列号表示选中该项,回车继续选择,如果已选好,直接回车回到命令主界面
git add --ignore-removal .
添加工作区 修改 或 新增 的文件列表, 删除 的文件不会被添加
git commit

“把暂存区的文件提交到本地版本库
git commit -m '第一行提交原因'  -m '第二行提交原因'
不打开编辑器,直接在命令行中输入多行提交原因
git commit -am '提交原因'
将工作区 修改 或 删除 的文件提交到本地版本库, 新增 的文件不会被提交
git commit --amend -m '提交原因'
修改最新一条提交记录的提交原因
git commit -C HEAD
将当前文件改动提交到 HEAD 或当前分支的历史ID
git mv

“移动或重命名文件、目录
git mv a.md b.md -f
将 a.md 重命名为 b.md ,同时添加变动到暂存区,加 -f 参数可以强制重命名,相比用 mv a.md b.md 命令省去了 git add 操作
git rm

“从工作区和暂存区移除文件
git rm b.md
从工作区和暂存区移除文件 b.md ,同时添加变动到暂存区,相比用 rm b.md 命令省去了 git add 操作
git rm src/ -r
允许从工作区和暂存区移除目录
git status

git status -s
以简短方式查看工作区和暂存区文件状态,示例如下:
M demo.html?? test.htmlgit status --ignored
查看工作区和暂存区文件状态,包括被忽略的文件
操作分支

git branch

“查看、创建、删除分支
git branch -a
查看本地版本库和远程版本库上的分支列表
git branch -r
查看远程版本库上的分支列表,加上 -d 参数可以删除远程版本库上的分支
git branch -D
分支未提交到本地版本库前强制删除分支
git branch -vv
查看带有最后提交id、最近提交原因等信息的本地版本库分支列表

git merge

“将其它分支合并到当前分支
git merge --squash
将待合并分支上的 commit 合并成一个新的 commit 放入当前分支,适用于待合并分支的提交记录不需要保留的情况



git merge --no-ff
默认情况下,Git 执行"快进式合并"(fast-farward merge),会直接将 Master分支指向 Develop 分支,使用 --no-ff 参数后,会执行正常合并,在 Master分支上生成一个新节点,保证版本演进更清晰。

git merge --no-edit
在没有冲突的情况下合并,不想手动编辑提交原因,而是用 Git 自动生成的类似 Merge branch 'test' 的文字直接提交
git checkout

“切换分支
git checkout -b daily/0.0.1
创建 daily/0.0.1 分支,同时切换到这个新创建的分支
git checkout HEAD demo.html
从本地版本库的 HEAD(也可以是提交ID、分支名、Tag名) 历史中检出 demo.html 覆盖当前工作区的文件,如果省略 HEAD 则是从暂存区检出
git checkout --orphan new_branch
这个命令会创建一个全新的,完全没有历史记录的新分支,但当前源分支上所有的最新文件都还在,真是强迫症患者的福音,但这个新分支必须做一次 git commit操作后才会真正成为一个新分支。
git checkout -p other_branch
这个命令主要用来比较两个分支间的差异内容,并提供交互式的界面来选择进一步的操作,这个命令不仅可以比较两个分支间的差异,还可以比较单个文件的差异。
git stash

“在 Git 的栈中保存当前修改或删除的工作进度,当你在一个分支里做某项功能开发时,接到通知把昨天已经测试完没问题的代码发布到线上,但这时你已经在这个分支里加入了其它未提交的代码,这个时候就可以把这些未提交的代码存到栈里。
git stash
将未提交的文件保存到Git栈中
git stash list
查看栈中保存的列表
git stash show stash@{0}
显示栈中其中一条记录
git stash drop stash@{0}
移除栈中其中一条记录
git stash pop
从Git栈中检出最新保存的一条记录,并将它从栈中移除
git stash apply stash@{0}
从Git栈中检出其中一条记录,但不从栈中移除
git stash branch new_banch
把当前栈中最近一次记录检出并创建一个新分支
git stash clear
清空栈里的所有记录
git stash create
为当前修改或删除的文件创建一个自定义的栈并返回一个ID,此时并未真正存储到栈里
git stash store xxxxxx
将 create 方法里返回的ID放到 store 后面,此时在栈里真正创建了一个记录,但当前修改或删除的文件并未从工作区移除
$ git stash create09eb9a97ad632d0825be1ece361936d1d0bdb5c7$ git stash store 09eb9a97ad632d0825be1ece361936d1d0bdb5c7$ git stash liststash@{0}: Created via "git stash store".
操作历史

git log

“显示提交历史记录
git log -p
显示带提交差异对比的历史记录
git log demo.html
显示 demo.html 文件的历史记录
git log --since="2 weeks ago"
显示2周前开始到现在的历史记录,其它时间可以类推
git log --before="2 weeks ago"
显示截止到2周前的历史记录,其它时间可以类推
git log -10
显示最近10条历史记录
git log f5f630a..HEAD
显示从提交ID f5f630a 到 HEAD 之间的记录,HEAD 可以为空或其它提交ID
git log --pretty=oneline
在一行中输出简短的历史记录
git log --pretty=format:"%h"
格式化输出历史记录
Git 用各种 placeholder 来决定各种显示内容,我挑几个常用的显示如下:

  • %H: commit hash
  • %h: 缩短的commit hash
  • %T: tree hash
  • %t: 缩短的 tree hash
  • %P: parent hashes
  • %p: 缩短的 parent hashes
  • %an: 作者名字
  • %aN: mailmap的作者名
  • %ae: 作者邮箱
  • %ad: 日期 (--date= 制定的格式)
  • %ar: 日期, 相对格式(1 day ago)
  • %cn: 提交者名字
  • %ce: 提交者 email
  • %cd: 提交日期 (--date= 制定的格式)
  • %cr: 提交日期, 相对格式(1 day ago)
  • %d: ref名称
  • %s: commit信息标题
  • %b: commit信息内容
  • %n: 换行
git cherry-pick

“合并分支的一条或几条提交记录到当前分支末梢
git cherry-pick 170a305
合并提交ID 170a305 到当前分支末梢
git reset

“将当前的分支重设(reset)到指定的 <commit> 或者 HEAD
git reset --mixed <commit>
--mixed 是不带参数时的默认参数,它退回到某个版本,保留文件内容,回退提交历史
git reset --soft <commit>
暂存区和工作区中的内容不作任何改变,仅仅把 HEAD 指向 <commit>
git reset --hard <commit>
自从 <commit> 以来在工作区中的任何改变都被丢弃,并把 HEAD 指向 <commit>
git rebase

“重新定义分支的版本库状态
git rebase branch_name
合并分支,这跟 merge 很像,但还是有本质区别,看下图:

合并过程中可能需要先解决冲突,然后执行 git rebase --continue

git rebase -i HEAD~~
打开文本编辑器,将看到从 HEAD 到 HEAD~~ 的提交如下
pick 9a54fd4 添加commit的说明pick 0d4a808 添加pull的说明# Rebase 326fc9f..0d4a808 onto d286baa## Commands:#  p, pick = use commit#  r, reword = use commit, but edit the commit message#  e, edit = use commit, but stop for amending#  s, squash = use commit, but meld into previous commit#  f, fixup = like "squash", but discard this commit's log message#  x, exec = run command (the rest of the line) using shell#
将第一行的 pick 改成 Commands 中所列出来的命令,然后保存并退出,所对应的修改将会生效。如果移动提交记录的顺序,将改变历史记录中的排序。
git revert

“撤销某次操作,此次操作之前和之后的 commit 和 history 都会保留,并且把这次撤销作为一次最新的提交
git revert HEAD
撤销前一次提交操作
git revert HEAD --no-edit
撤销前一次提交操作,并以默认的 Revert "xxx" 为提交原因
git revert -n HEAD
需要撤销多次操作的时候加 -n 参数,这样不会每次撤销操作都提交,而是等所有撤销都完成后一起提交
git diff

“查看工作区、暂存区、本地版本库之间的文件差异,用一张图来解释

git diff --stat
通过 --stat 参数可以查看变更统计数据
test.md | 1 - 1 file changed, 1 deletion(-)
git reflog

reflog 可以查看所有分支的所有操作记录(包括commit和reset的操作、已经被删除的commit记录,跟 git log 的区别在于它不能查看已经删除了的commit记录



远程版本库连接

如果在GitHub项目初始化之前,文件已经存在于本地目录中,那可以在本地初始化本地版本库,再将本地版本库跟远程版本库连接起来
git init

“在本地目录内部会生成.git文件夹
git remote

git remote -v
不带参数,列出已经存在的远程分支,加上 -v 列出详细信息,在每一个名字后面列出其远程url
git remote add origin https://github.com/gafish/gafish.github.com.git
添加一个新的远程仓库,指定一个名字,以便引用后面带的URL
git fetch

“将远程版本库的更新取回到本地版本库
git fetch origin daily/0.0.1
默认情况下,git fetch 取回所有分支的更新。如果只想取回特定分支的更新,可以指定分支名。
问题排查

git blame

“查看文件每行代码块的历史信息
git blame -L 1,10 demo.html
截取 demo.html 文件1-10行历史信息
git bisect

“二分查找历史记录,排查BUG
git bisect start
开始二分查找
git bisect bad
标记当前二分提交ID为有问题的点
git bisect good
标记当前二分提交ID为没问题的点
git bisect reset
查到有问题的提交ID后回到原分支
更多操作

git submodule

“通过 Git 子模块可以跟踪外部版本库,它允许在某一版本库中再存储另一版本库,并且能够保持2个版本库完全独立
git submodule add https://github.com/gafish/demo.git demo
将 demo 仓库添加为子模块
git submodule update demo
更新子模块 demo
git gc

“运行Git的垃圾回收功能,清理冗余的历史快照
git archive

“将加了tag的某个版本打包提取
git archive -v --format=zip v0.1 > v0.1.zip
--format 表示打包的格式,如 zip,-v 表示对应的tag名,后面跟的是tag名,如 v0.1。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表