初探Git:理解和使用版本控制的魔法
在古老的传说中,有一位美丽的仙女叫做嫦娥。她的丈夫后羿获得了令人长生不老的鹿骨露。一天,嫦娥在好奇心的驱使下,独自偷喝了这瓶仙药。 喝下仙药的瞬间,嫦娥发现自己开始飘起,越飘越高,最后飘向了月亮。嫦娥惊慌失措,她突然意识到,自己做了一个错误的决定,她非常后悔,但一切已经无法改变,她只能在月亮上度过寂寞的生活。
如果嫦娥的世界有Git这样的版本控制工具,事情可能会完全不同。她偷喝仙药的决定就像我们在编程时对代码的修改,而她后悔的感觉,就像我们在发布代码后发现了重大的错误。 如果之前喝仙药的决定被记录在Git中,进行一次commit操作,嫦娥就可以使用git revert
撤销这个决定,就像撤销一次错误的代码提交。或者她可以使用git reset --hard
命令,回到偷喝仙药之前的状态,就像我们将代码回滚到之前的某个版本。
重写的故事也许有些荒诞,但它生动地描绘了Git工具的强大之处。在代码的世界里,我们有能力前进也可以后退;我们可以修正错误,也可以尝试新的可能。这种灵活性让我们可以更有信心地进行工作,因为我们知道,即使我们做了错误的决定,也总有机会改正它。这也正是Git所带给我们的,掌控历史进程的能力。下面就让我们一起来学习这个强大的工具吧。
一、Git是什么?
Git 是一个开源的分布式版本控制系统。 在项目开发中,开发人员通过 Git 追踪和协调他们代码的变化,以及将其历史版本记录下来,方便在需要时通过查阅历史版本进行问题的定位和修复。
二、为什么使用Git?
版本控制是软件开发的重要组成部分,对于代码更改的追踪和管理都显得至关重要。
Git不仅可用于版本控制,同时也是优秀的协作工具。当多名开发者同时工作在同一个项目中时,Git能够确保代码的同步并避免代码冲突。
此外,Git的存储效率和性能也非常高,能够快速地处理大量的操作和数据。
三、常用Git命令
接下来,我将一一介绍Git中常用的命令。
1.新建与配置
通过以下命令,可以新建一个Git代码仓库,也能够从网络上下载已有的项目:
git init
在当前目录新建一个Git代码库。git clone [url]
下载一个项目及其整个代码历史。
Git的设置存储在.gitconfig文件中,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。以下命令可以用于显示及编辑设置:
git config --list
显示当前的Git配置。git config -e [--global]
编辑Git配置文件。
2.增加与删除文件
增加或删除文件是日常工作中不可或缺的一部分,以下命令可帮助你完成这些工作:
git add [file1] [file2] ...
:用于将指定文件添加到暂存区。你可以一次添加多个文件,只需要在git add
后面列出文件的名字即可。git add [dir]
:此命令用于将指定目录(包括子目录)的所有文件添加到暂存区。git add .
:此命令用于添加当前目录的所有文件到暂存区。git rm [file]
: 此命令用于删除工作区的文件,并且将这次删除添加到暂存区。git rm --cached [file]
:此命令用于删除版本库的文件信息,但保留工作区的文件。这通常用于文件已经被纳入版本控制,但你希望忽略它们。
例如,当不小心将不需要提交的文件(比如包含敏感信息的配置文件)添加到了版本库,你需要移除版本库中的该文件,但在本地保留。这时,你可以使用
git rm --cached [file]
命令,接着在.gitignore
文件中添加对应要忽略的文件名,防止今后误提交。
3.代码提交
与代码相关的修改,都应通过以下命令提交到Git仓库中:
git commit -m [message]
提交暂存区到仓库区。git commit [file1] [file2] ... -m [message]
提交暂存区的指定文件到仓库区。git commit --amend -m [message]
使用新的commit,替代上一次的提交。git commit -a
: 自动把所有已经跟踪过的文件的更改(新增、修改、删除)都放到暂存区,然后执行一次 commit。git cherry-pick <commit-hash>
将特定的提交从一个分支应用(或称挑选)到另一个分支,生成新的【hash值不同的】提交。用于想要在不同的分支上修复同一个 bug,或者想要在主分支上迅速应用一个特性分支上的某个提交
4.分支新建与切换
在涉及多个开发人员或者需要同时进行多项任务时,分支是一种非常实用的功能。
git branch
:这个命令用于查看本地所有的分支。git branch -r
:查看远程所有分支。git branch [branch-name]
:新建一个分支,但仍停留在当前分支。git checkout -b [branch-name]
:新建一个分支,并切换到该分支。git checkout <branch-name> :
将当前的工作目录切换成<branch-name>
分支的代码。git switch <branch-name> :
将当前的工作目录切换成<branch-name>
分支的代码。
(checkout 命令和撤销修改相关,容易混淆,建议使用 Switch)
5.分支合并
-
git merge [branch]
:将指定分支合并到当前分支。 -
无冲突 默认使用快速合并
-
有冲突CONFLICT (content): Merge conflict in readme.txtAutomatic merge failed; fix conflicts and then commit the result.Git用
<<<<<<<Head,【此分支】=======【冲突分支】>>>>>>>
标记出不同分支的内容,需要解决冲突后提交: -
$ git add readme.txt
-
$ git commit -m "conflict fixed"
-
当你合并两个分支时,如果一个分支是另一个分支的直接祖先,Git会默认使用 "Fast-forward" 的方式将二者合并,即直接将指针向前移动。但如果它们的历史不完全一样,Git 会进行 "three-way merge",并自动创建一个新的 commit。
-
git merge --abort
取消正在进行的合并; -
git reset --hard [commit]
将整个分支回滚到合并前的状态。【取消合并的一种方法】 -
git rebase
[branch] 整合到特定分支。这将以特定分支为基础,应用当前分支上的每一个commit。这种策略用于你想使你的工作分支基于最新的develop或master。 -
git rebase --continue
解决完rebase冲突之后继续rebase。和merge类型,当rebase过程中出现冲突时,需要手动解决冲突。 -
git rebase --abort
取消当前进行的rebase操作,返回操作前的状态
对比 | Git Merge | Git Rebase |
---|---|---|
集成方式 | 通过创建一个新的提交来集成两个分支的更改,新的提交有两个父提交 | 通过在目标分支上重新应用当前分支的每一个提交来集成更改 |
提交历史 | 包含所有的分支和合并操作,可能会显得比较复杂 | 较为整洁,因为所有的更改都在一条直线上 |
解决冲突 | 只需解决一次冲突,然后创建一次合并提交 | 在应用每个分支提交时可能需要处理冲突,可能比较繁琐 |
6.标签操作
在大型项目中,使用标签(tag)来标记特定的提交点,如新的版本发布点,是一种很好地实践。
git tag
:列出所有的标签。git tag [tag]
: 在当前最新的提交上打一个新标签。git tag [tag] [commit-id]
: 在指定的提交上打一个新标签。git tag -d [tag-name]
:删除本地的一个标签。
7.查看信息
Git 提供了丰富的命令来帮助你查看项目的状态和历史记录:
git status
:显示当前工作区的状态,让你能看到哪些更改被暂存,哪些更改未被暂存,以及哪些文件未被 Git 追踪。git log
: 显示当前分支的提交历史。git log --oneline 在一行内展示
git log --stat
: 在git log基础上,显示每次提交修改过的文件git log -p
:查看每次详细的提交差异。git diff
: 此命令显示尚未暂存的改动对比,如果在git diff
后面跟上文件名,可以查看指定文件的改动。如果在git diff
后面跟上分支名,可查看当前工作区与对应分支的差异。git diff --cached
或git diff --staged
: 显示已经暂存但尚未提交的改动。
以上命令会给出部分信息,按↑↓键查看更多,输入 q 退出;同Vim 编辑器操作一致
8.远程同步
当你在团队中工作,或者想将你的项目发布到网络上时,你需要和远程的仓库进行交互。
git fetch [remote]
: 下载远程仓库的所有变动。并不会将远程的变动合并到你的本地代码,也不会修改你现在正在工作的代码。git pull [remote] [branch]
:git fetch
和git merge
的结合,它将下载远程代码并直接合并到本地。git push [remote] [branch]
: 将你的改动上传到远程仓库,其他人才可能看到你的改动。git branch --set-upstream [branch] [remote]
:在现有分支与指定的远程分支之间建立追踪关系。git push --force [remote] [branch]
: 将本地分支强制推送到远程仓库,即使远程版本更新,但需谨慎,可能删除他人的提交。git fetch --all / git fetch --prune:
其中--all
从远程仓库获取所有分支的最新更新。--prune
更新本地仓库,删除已被远程删除的分支。
9.撤销操作
我们工作中,总是会存在想撤销某些操作的情况,Git 提供了撤销操作的命令:
git checkout -- [file]
:撤销工作区的改动,将文件恢复到最近一次 commit 或者 add 的状态。git reset [file]
:会撤销已经暂存的文件,但并不会撤销工作区的修改。git revert [commit-id]
:撤销指定的提交,具体来说,它会创建一个新的提交,该提交的内容与需要被撤销的提交相反。git reset [commit]或者 git reset --soft [commit]
撤销所有[commit]
后的的提交,在本地保存更改git reset --hard [commit]
立刻撤销所有指定commit之后的提交,并且清除工作区的所有修改,使得当前状态反映的是指定commit时的状态
使用带有commit-id的命令时(如
git revert [commit-id]
,git reset --hard/soft [commit]
),commit-id必须是存在的才有效,可以通过git log
来查看所有的提交记录和相应的commit-id。
- 在使用这些命令时请慎重,因为一些操作在完成之后无法返回。
10.临时存放
有时候,你想临时保存当前工作目录的修改,并将工作目录恢复到干净的状态,以便切换分支或处理其他任务,可以使用 stash 命令临时保存。
git stash
:将当前工作目录的修改保存到一个新的存储区(stash)。将暂存区和工作区的修改都保存起来,并将工作目录恢复到干净的状态。git stash save "message"
:保存当前工作目录的修改,并添加一个描述性的消息。git stash list
:列出当前存储区中的所有存储项(stash)。每个存储项都有一个唯一的标识符(stash@{n}),并显示保存时的提交消息。git stash show
:显示最新的存储项(stash)的详细信息,包括修改的文件列表和文件的 diff。git stash show stash@{n}
:显示指定存储项的详细信息。git stash apply
:将最新的存储项应用到当前分支,并保留存储项。将存储项的修改应用到当前工作目录,但不会从存储区移除存储项。git stash apply stash@{n}
:将指定的存储项应用到当前分支,并保留存储项。git stash pop
:将最新的存储项应用到当前分支,并从存储区移除存储项。将存储项的修改应用到当前工作目录,并从存储区移除存储项。git stash drop
:移除最新的存储项(stash)。这个命令会从存储区移除最新的存储项,但不会影响工作目录的状态。git stash drop stash@{n}
:移除指定的存储项。git stash clear
:移除所有的存储项。
有时一些文件最好不要用 Git 跟踪。这通常在名为
.gitignore
的特殊文件中完成。你可以在 github.com/github/gitignore 找到有用的.gitignore
文件模板。
总结
- 每一次填写完对应 "跳转命令" 后,当前的工作环境就会改变。比如说,当你执行
git add <file>
后,指定的文件就会被添加到暂存区,当你执行git commit -m 'message'
后,暂存区的所有改动就会被提交到版本库。
名称 | 描述 | 跳转命令 |
---|---|---|
Workspace 工作区 | 当前正在工作的目录,包含了你可以看到和编辑的文件。 | 文件夹下文件的任意修改 |
Cached / Stage 暂存区 | 保存了下次将提交的文件列表信息,记录了文件的变更信息。 | git add <file/directory> 将修改添加到暂存区 |
Repository 版本库 | 存储了所有的管理信息,包括各个版本的提交信息,记录了项目的版本变更历史。 | git commit -m 'message' 提交暂存区的改动到版本库 |
Remote远程仓库 | 在团队中工作,或者想将你的项目发布到网络上时使用 | `git push <remote><branch>` 推送本地仓库到远程分支, `git pull <remote><branch>` 从远程拉取内容到本地 |
stash区 | 临时保存工作进度的地方,不影响工作区和版本库状态。 | git stash 存储当前进度,git stash pop/apply 恢复之前的进度 |
本文只是浅尝辄止地了解了一些 Git 的命令,Git 仍有许多强大的功能等待我们去发掘。无论你处于何种程度,希望这篇文章可以帮助你更好地理解和使用 Git。
参考
https://www.runoob.com/wp-content/uploads/2015/02/011500266295799.jpg
https://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
https://training.github.com/downloads/zh_CN/github-git-cheat-sheet/