Git
这个答案包括 GitHub,因为许多人也曾问过这个问题。
本地存储库
Git(本地)有一个目录 (.git),您可以将文件提交到该目录,这是您的“本地存储库”。这与 SVN 等系统不同,您可以立即添加并提交到远程存储库。
Git 通过保存整个文件来存储文件更改的每个版本。在这方面它也与 SVN 不同,因为您可以转到任何单独的版本,而无需通过 delta 更改“重新创建”它。
Git 根本不“锁定”文件,因此避免了编辑时的“独占锁定”功能(想到像 pvcs 这样的旧系统),因此即使在离线时也可以随时编辑所有文件。实际上,它在将文件更改(在同一个文件中!)合并到一个远程存储库(如 GitHub)期间完成了一项了不起的工作。唯一需要手动更改(实际上是编辑文件)的情况是两个更改涉及相同的代码行。
分支机构
分支允许您保留主要代码(“主”分支)、制作副本(新分支),然后在该新分支中工作。如果工作需要一段时间,或者 master 在创建分支后得到了很多更新,那么应该针对 master 分支进行合并或变基(通常是更好的历史记录和更容易解决冲突的首选)。完成后,将分支中所做的更改合并回主存储库。许多组织对每项工作都使用分支,无论是功能、错误还是杂项。其他组织仅将分支用于版本升级等重大更改。
Fork:通过分支,您可以控制和管理分支,而通过 fork,其他人可以控制接受代码返回。
一般来说,有两种主要的方法来做分支。第一个是将大多数更改保留在主分支上,仅将分支用于更大且运行时间更长的事情,例如版本更改,您希望有两个分支可用于不同的需求。第二个是您基本上为每个功能请求、错误修复或杂务创建一个分支,然后手动决定何时将这些分支实际合并到主主分支中。虽然这听起来很乏味,但这是一种常见的方法,也是我目前使用和推荐的方法,因为这可以保持主分支更清洁,并且它是我们提升到生产环境的主分支,所以我们只需要完成、测试过的代码,通过变基和合并分支。
将分支“引入”到 master 的标准方法是执行merge。分支也可以“重新定位”以“清理”历史记录。它不会影响当前状态,这样做是为了提供“更清晰”的历史记录。
基本上,这个想法是您从某个点(通常从 master)分支。自从你分支以来,'master' 本身已经从那个分支点向前移动了。如果您在分支中所做的所有更改都针对 master 的当前状态及其所有最新更改,它将是“更干净”(更容易解决问题并且历史将更容易理解)。所以,过程是:保存更改;获取“新”主控,然后重新应用(这是变基部分)再次针对该更改进行更改。请注意,与合并一样,rebase 可能会导致您必须手动解决(即编辑和修复)的冲突。
需要注意的一条准则:
仅当分支位于本地且您尚未将其推送到远程时才重新设置基准!
这主要是因为变基可以改变其他人看到的历史记录,其中可能包括他们自己的提交。
跟踪分支
这些分支被命名为origin/branch_name(而不仅仅是branch_name)。当您向远程存储库推送和拉取代码时,这实际上是发生这种情况的机制。例如,当您 git push 一个名为 building_groups 的分支时,您的分支首先转到 origin/building_groups,然后转到远程存储库。同样,如果您执行git fetch building_groups,则检索到的文件将放置在您的origin/building_groups 分支中。然后,您可以选择将此分支合并到您的本地副本中。我们的做法是始终执行git fetch 和手动合并,而不仅仅是git pull(一步完成以上两项)。
获取新分支。
获取新分支:在克隆的初始点,您将拥有所有分支。但是,如果其他开发人员添加分支并将它们推送到远程,则需要有一种方法来“了解”这些分支及其名称,以便能够在本地将它们拉下来。这是通过git fetch 完成的,它将使用跟踪分支(例如origin/)将所有新的和更改的分支放入本地存储库。一旦fetched,可以git branch --remote 列出跟踪分支,git checkout [branch] 实际切换到任何给定的分支。
合并
合并是合并来自不同分支或同一分支的不同版本的代码更改的过程(例如,当本地分支和远程不同步时)。如果一个人在一个分支中开发了工作并且该工作已经完成、准备好并经过测试,那么它可以合并到master 分支中。这是由git checkout master 切换到master 分支,然后git merge your_branch 完成的。合并会将所有不同的文件和甚至对同一文件的不同更改结合在一起。这意味着它实际上会更改文件内的代码以合并所有更改。
在执行master 的checkout 时,还建议执行git pull origin master 以将最新版本的远程主机合并到本地主机中。如果远程主机发生变化,即moved forward,您将看到在git pull 期间反映该情况的信息。如果是这种情况(master 已更改),建议您先使用 git checkout your_branch,然后将 rebase 改为 master,这样您的更改实际上会在“新”master 之上“重播”。然后,您将继续使 master 保持最新,如下一段所示。
如果没有冲突,那么 master 将添加新的更改。如果有冲突,这意味着相同的文件在相似的代码行周围有更改,它不能自动合并。在这种情况下,git merge new_branch 将报告有冲突需要解决。您可以通过编辑文件(其中包含两个更改)、选择您想要的更改、从字面上删除您不想要的更改的行然后保存文件来“解决”它们。更改用======== 和<<<<<<<< 等分隔符标记。
一旦您解决了任何冲突,您将再次 git add 和 git commit 这些更改以继续合并(在此过程中您将获得来自 git 的反馈以指导您)。
当过程不顺利时,您会发现git merge --abort 非常方便重置。
交互式变基和压缩/重新排序/删除提交
如果您已经完成了很多小步骤的工作,例如,您每天都将代码提交为“正在进行的工作”,那么您可能希望将这些小提交“压缩”成几个更大的提交。当您想与同事进行代码审查时,这可能特别有用。您不想重播您采取的所有“步骤”(通过提交),您只想说这是我在一次提交中对这项工作所做的所有更改的最终效果(差异)。
在考虑是否这样做时要评估的关键因素是多个提交是否针对同一个文件或多个文件(在这种情况下最好压缩提交)。这是通过交互式变基工具完成的。此工具可让您压缩提交、删除提交、改写消息等。例如,git rebase -i HEAD~10(注意:这是~,而不是-)会显示以下内容: p>
不过要小心并“谨慎地”使用此工具。一次执行一个 squash/delete/reorder,退出并保存该提交,然后重新进入该工具。如果提交不连续,您可以重新排序它们(然后根据需要压缩)。您实际上也可以在此处删除提交,但您确实需要确定在执行此操作时您在做什么!
分叉
在 Git 存储库中有两种主要的协作方法。上面详述的第一个是直接通过人们拉出/推入的分支。这些协作者的 SSH 密钥已注册到远程存储库。这将让他们直接推送到该存储库。缺点是您必须维护用户列表。
另一种方法 - 分叉 - 允许任何人“分叉”存储库,基本上是在他们自己的 Git 存储库帐户中制作本地副本。然后他们可以进行更改,并在完成后发送“拉取请求”(实际上,这更像是来自他们的“推送”和对实际存储库维护者的“拉取”请求)以使代码被接受。
第二种方法使用分叉,不需要有人维护存储库的用户列表。
GitHub
GitHub(远程存储库)是一个远程源,如果您拥有(或被添加到)这样的存储库,您通常会将这些已提交的更改推送和拉取到,因此本地和远程实际上是完全不同的。考虑远程存储库的另一种方式是它是一个位于远程服务器上的.git 目录结构。
当您“分叉”时 - 在 GitHub 网络浏览器 GUI 中,您可以单击此按钮 - 您在您的 GitHub 帐户中创建代码的副本(“克隆”)。第一次这样做可能有点微妙,所以请务必查看代码库在哪个存储库下列出 - 原始所有者或“派生自”以及您,例如,像这样:
获得本地副本后,您可以根据需要进行更改(通过拉取并推送到本地计算机)。完成后,您向原始存储库所有者/管理员提交一个“拉取请求”(听起来很花哨,但实际上您只需点击此:)然后他们“拉取”它。
对于一起处理代码的团队来说,更常见的是“克隆”存储库(单击存储库主屏幕上的“复制”图标)。然后,在本地输入git clone 并粘贴。这将在本地设置您,您还可以推送和拉到(共享)GitHub 位置。
克隆
如 GitHub 部分所述,克隆是存储库的副本。当您拥有远程存储库时,您可以针对其 URL 发出 git clone 命令,然后您将获得该存储库的本地副本或克隆。这个克隆有一切、文件、master 分支、其他分支、所有现有的提交、整个 shebang。您对这个克隆进行添加和提交,然后远程存储库本身就是您将这些提交推送到的内容。正是这种本地/远程概念使 Git(以及与其类似的系统,例如 Mercurial)成为 DVCS(分布式 版本控制系统),而不是更传统的 CVS(代码版本控制系统),例如 SVN, PVCS、CVS 等,您可以直接提交到远程存储库。
可视化
核心概念的可视化可见
http://marklodato.github.com/visual-git-guide/index-en.html和
http://ndpsoftware.com/git-cheatsheet.html#loc=index
如果您想要直观地显示更改的工作方式,您无法使用可视化工具 gitg(对于 macOS 为 gitx)使用我称之为“地铁地图”的 GUI(尤其是伦敦地铁) ),非常适合展示谁做了什么、事情如何变化、分歧和合并等。
您还可以使用它来添加、提交和管理您的更改!
虽然 gitg/gitx 相当少,但 GUI 工具的数量仍在不断增加。许多 Mac 用户使用 Brotherbard 的 gitx 分支,对于 Linux,一个不错的选择是 smart-git,它具有直观而强大的界面:
请注意,即使使用 GUI 工具,您也可能会在命令行中执行大量命令。
为此,我的~/.bash_aliases 文件中有以下别名(每个终端会话从我的~/.bashrc 文件中调用):
# git
alias g='git status'
alias gcob='git checkout -b '
alias gcom='git checkout master'
alias gd='git diff'
alias gf='git fetch'
alias gfrm='git fetch; git reset --hard origin/master'
alias gg='git grep '
alias gits='alias | grep "^alias g.*git.*$"'
alias gl='git log'
alias gl1='git log --oneline'
alias glf='git log --name-status'
alias glp='git log -p'
alias gpull='git pull '
alias gpush='git push '
我的~/.gitconfig 文件中有以下“git 别名” - 为什么有这些?
这样分支完成(使用 TAB 键)就可以了!
所以这些是:
[alias]
co = checkout
cob = checkout -b
示例用法:git co [branch]
图形化学习工具
您可能会发现https://learngitbranching.js.org/ 有助于学习一些基本概念。截图:
视频:https://youtu.be/23JqqcLPss0
最后,7 个关键的救星!
-
您进行更改,添加并提交它们(但不要推送)然后哦!你意识到你是大师!
git reset [filename(s)]
git checkout -b [name_for_a_new_branch]
git add [file(s)]
git commit -m "A useful message"
Voila! You've moved that 'master' commit to its own branch !
-
您在本地分支中工作时弄乱了一些文件,只是想回到上次执行git pull 时的内容:
git reset --hard origin/master # You will need to be comfortable doing this!
-
您开始在本地进行更改,您编辑了六个文件,然后,哦,废话,您仍然在主(或另一个)分支中:
git checkout -b new_branch_name # just create a new branch
git add . # add the changes files
git commit -m"your message" # and commit them
-
您弄乱了当前分支中的一个特定文件,并希望基本上将该文件“重置”(丢失更改)到您上次从远程存储库中提取它时的状态:
git checkout your/directories/filename
这实际上重置了文件(就像许多 Git 命令一样,它在这里所做的事情并没有很好地命名)。
-
您在本地进行了一些更改,您想确保在执行 git reset 或 rebase 时不会丢失它们:我经常手动复制整个项目 (cp -r ../my_project ~/)不确定我是否会在 Git 中搞砸或丢失重要的更改。
-
你正在变基,但事情变得一团糟:
git rebase --abort # To abandon interactive rebase and merge issues
-
将您的 Git 分支添加到您的 PS1 提示符(参见 https://unix.stackexchange.com/a/127800/10043),例如
分支是selenium_rspec_conversion。