Git 30个常见问题

Git已经成为开发过程不可或缺的版本控制工具,经常要使用那些命令不多,如果每次使用的时候再去查看用法效率极其低下,这里总结了下30个Git中碰到的使用问题,掌握了这些Git你就会了80%。

如何创建新的 git 存储库?

git init
git add .
git commit -m ‘initial commit’
git remote add origin 
git push -u origin master

如何只添加文件的一部分?

git add --patch 

这将打开一个交互式界面,该界面可以在对文件的每个单独更改中移动,从而允许您仅暂存您想要的更改。

$ git add --patch package.json
diff --git a/package.json b/package.json
index 7a558a3..e03ce3f 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,6 @@
   "name": "package",
   "version": "0.4.3",
   "description": "this is an example package",
-  "keywords": ["key", "middleware", "connect"],
   "repository": "git://github.com/foo/bar.git",
   "author": "Joe Smith  (http://google.com)",
   "repository": "git://github.com/foo/bar",
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y

我如何压缩提交?

有多种压缩提交的方法,但最推荐和最直接的是使用交互式 rebase,例如

git rebase -i HEAD~4 # interactively rebase from 3 commits ago

此命令将打开您的编辑器,其中包含一些有用的文档以及这些提交和消息的列表。提交按顺序列出,最旧的提交在顶部,最新的提交在底部。

pick f53d15b fixed edge case with IE5
pick 930c0e5 added code coverage
pick fa7c471 fixed lint errors
pick fb57c85 added feature Foo

# Rebase 0a4b808..db5d725 onto 0a4b808
#
# 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
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

壁球在过去4个到提交最近,你会改变pick,以squash对提交2,3和4。

pick f53d15b fixed edge case with IE5
squash 930c0e5 added code coverage
squash fa7c471 fixed lint errors
squash fb57c85 added feature Foo

当文件被保存并退出编辑器时,git 会自动将这 4 个提交压缩为一个。然后您的编辑器将再次弹出,允许您更改结果提交的提交消息。

如何更改我的最后一次提交消息?

git commit --amend --only

或者,没有分阶段更改:

git commit --amend

--amend如果没有其他选项,将当前暂存的更改与上次提交组合在一起,然后打开一个编辑器来更新提交消息。如果您进行了分阶段更改,它们将被添加。

要更新最后一条消息,即使有分阶段的更改(git status报告下的文件Changes to be committed),您可以使用-o(或--only)选项来指示您要修改最后一次提交,但仅使用先前提交的文件。

如何更改我尚未推送的提交的内容

git commit --amend 

要么

git commit --amend --all

如果不需要更改提交消息,则添加--no-edit例如

git commit --amend --all --no-edit

git add file.js # stage the file
git commit      # commit the file

我如何比较分支?

在远程master分支上查找不在我们本地master分支上的提交:

git cherry -v origin/master master

在本地master分支上查找不在我们本地feature分支上的提交:

git cherry -v master feature

查找自1.0.0标记以来添加的提交:

git cherry -v v1.0.0 master

如何创建分支?

git branch       # just creates a branch off the current sha
git checkout     # actually moves to the branch

这可以简化为:

git checkout -b  # branches and moves to the branch in one command

如何获取自提交以来已更改的文件列表?

从类似的命令中获取适当的哈希值后 git log

git diff --name-only cda409f...

如何删除分支?

删除本地分支feature

git branch -d feature

如果分支没有合并,这将失败。无论如何删除分支:

git branch -D feature

feature在远程删除远程分支origin(警告:没有确认!):

git push origin :feature

注意:git-branch文档列出了-r适用于远程_跟踪_分支的选项的文档,而不是远程分支;git branch -D -r origin/feature将删除远程跟踪分支origin/feature,而不是feature远程分支origin。再次从远程拉取/获取将重新创建该跟踪分支。

要删除远程上不再存在的远程跟踪分支:

git fetch --prune

如何推送我的更改?

git push
git push origin branch-name

如何忽略文件模式?

git ignore '*.swp'

如果您还没有忽略任何内容,这将创建一个.gitignore您可能想要添加和跟踪的文件。

git add .gitignore
git commit -m 'added .gitignore'

如何完全重置我的本地存储库?

git reset
git checkout .
git clean -fdx

如何撤消提交?

您想撤消提交并且再也看不到更改吗?

git reset --hard HEAD~1

您想保留您的更改并撤消实际的提交行为吗?

git reset HEAD~1

如何还原所有未提交的更改?

git checkout .        # reset all tracked files
git checkout file.txt # reset file.txt
git checkout somedir/ # reset all files in somedir/

git reset --hard HEAD

如何删除所有未跟踪的文件?

git clean -fd

如何更新我的存储库?

git pull [remote] [branch]

使用 rebase 更新:

git pull --rebase [remote] [branch]

这与上面的执行相同,但使用rebase代替merge


如何撤消 git add?

git reset

要么

git reset file.txt

git add只需将要提交的更改分阶段进行。要撤消该操作,只需要git reset文件或文件列表即可。


如果我忘记在上次提交中添加文件怎么办?

git add file.js     # the file that needed to be included
git commit --amend  # amend the commit done before step 1 with the added file

这会将文件添加到之前的提交中,并将其替换为新的提交。

这可以简化为一个命令:

git commit --amend file.js

如果不需要更新提交消息:

git commit --amend --no-edit file.js

如果需要将所有编辑过的文件添加到最后一次提交:

git commit --amend --no-edit --all

“改变历史”是什么意思?

在 git 中,每个提交都标记有唯一的SHA -1 哈希值。在解决出现分歧的来源之间的差异时,这些至关重要。这一系列 SHA 被称为“历史”,而“改变历史”正在通过任意数量的合法手段重新生成这些哈希。

修改后的历史使得解决两个存储库之间的差异变得非常困难,因为从 git 的角度来看,SHA 已经更改,并且_应该_引用相同更改的提交现在看起来是不同时间的两个不同更改。

重写历史有许多合法用途,但需要与已经基于要更改的历史进行开发的人数成正比的沟通。在重写历史之前解决更改是很重要的,这通常意味着等待所有重要的工作被推送。

重写_本地历史_直到共享更改很少成为问题。您需要与之交流的人数通常仅限于您。

在共享功能分支上,与您在该分支上一起开发的人员的沟通负担会增加。如果您期望分支是短暂的和高度协作的(假设高度沟通),这通常也不是问题。

在任何人都可以基于任何任意工作(例如“master”或“develop”)的主线分支上,更改历史记录是非常成问题的,并且只能在了解成本的极端情况下进行。之所以会出现问题,是因为您几乎无法确定您是否已与您需要的_每个人进行了_沟通,以确保在历史修改之前推送重要更改。


什么是“分离头”?

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

这不是错误消息,无需担心。这只是一个通知,表明您没有连接到实际的分支。例如,在 上进行以下提交master

master    A-B-C-D-E-F-G

使用上面的示例,其中master分支具有 commits A-G,如果您签出 master ,您将被放置在 master 的“尖端” commit 处G。如果你停留在树枝的顶端,你就被认为是“依附的”。

如果您签出任意提交,则您不再一定与分支相关联并被视为“分离”。

这对于探索提交时的代码状态很有用,您还可以创建分支并将其从“分离头”状态移动到分支。

如果此状态是无意的,您可以通过检查您希望所在的分支返回到您可能想要的位置,例如

$ git checkout master
Previous HEAD position was 183409d... added file.txt
Switched to branch 'master'

尝试自己浏览分离的头部。以下块设置了一个新的 git 存储库,其中包含两次提交。

git init
touch file.txt
git add file.txt
git commit -m 'added file.txt'
touch file2.txt
git add file2.txt
git commit -m 'added file2.txt'

HEAD现在在大师的尖端。通过发出git checkout HEAD~1引用之前提交 1的命令来检查之前的提交HEAD

$ git checkout HEAD~1
git co HEAD~1
Note: checking out 'HEAD~1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 183409d... added file.txt

为了回到主人的尖端,checkout master.

$ git checkout master
Previous HEAD position was 183409d... added file.txt
Switched to branch 'master'

但是请注意,如果您尝试检查 master 的提示最初指向您的提交内容,仍然会被分离!

$ git co ec3...7da
Previous HEAD position was 183409d... added file.txt
HEAD is now at ec36c1b... added file2.txt
$ git status
HEAD detached at ec36c1b
nothing to commit, working directory clean

什么是“远程”?

术语“远程”是您可能想要推送或拉取的任何远程目标。这通常是托管在 git 服务器上的 git 存储库,如由 Github 运行的那些。

您可以有多个远程。

您可以查看您设置的远程git remotegit remote -v为您提供更多重要信息。

$ git remote -v
origin    git@github.com:jsoverson/gitfaq.git (fetch)
origin    git@github.com:jsoverson/gitfaq.git (push)

您可以通过git remote add <destination>例如添加新远程

$ git remote add michaelficarra git@github.com:michaelficarra/gitfaq.git

您可以通过更改目的地 git remote set-url <remote> <destination>

$ git remote set-url origin git@github.com:michaelficarra/gitfaq.git

什么是本地历史/共享历史?

“远程历史”或“共享历史”用于指代与他人共享的历史。“本地历史”用于指代从未共享的更改。

对于以下提交历史,显示了“共享历史”和“本地历史”边界,

A-B-C-D-E                origin/master

A-B-C-D-E-F-G-H-I        origin/feature1

A-B-C-D-E-F-G-H-I-J-K-J  feature1 (local)
|       | |     | |   |
|       | |     | +-+-+
|       | |     |   |
|       | +--+--+   Local History
|       |    |
+---+---+  Shared History (branch)
    |
Shared History (master)

什么是“起源”?

Origin 是远程服务器的默认名称。“remote”可以任意命名,您可以使用命令查看所有远程的名称remote

$ git remote -v
origin    git@github.com:jsoverson/gitfaq.git (fetch)
origin    git@github.com:jsoverson/gitfaq.git (push)

什么是变基

Rebase 正在为一系列提交建立一个新的基础。

在下面的示例中,分支feature在 commit处偏离B,而master分支并行移动。

A-B-C-D-E    master
   \
    X-Y-Z    feature

您可以使用rebase命令变基。例如,要将feature分支变基为master

$ git checkout feature
$ git rebase master

Rebase 本质上是在分支上回滚提交,使分支与 rebase 目标保持同步,然后在它上面重放回滚提交,使时间线看起来像这样。

A-B-C-D-E        master
         \
          X'-Y'-Z'  feature

什么是压缩?

压缩是将多个 git 提交变成更少的行为。您可能想要这样做的原因有很多,但最直接的方法是简单地保持提交历史记录更清晰并填充高价值的更改。

考虑以下一组提交

f53d15b fixed edge case with IE5
930c0e5 increased code coverage
fa7c471 fixed lint errors
fb57c85 added feature Foo

在本地存储库中,该级别的详细信息可能有用;在某些时候,在修复 lint 错误时可能会引入回归,您将能够恢复到之前的提交以进行一些测试。

这种粒度级别变得比其价值更嘈杂。在准备代码以进入主线分支时,将提交压缩成逻辑块会变得更有价值,这样历史作为重要更改的记录就变得更有价值。然后可以将以下提交压缩为单个提交,例如

a3545a5 added feature Foo

master 和 HEAD 和有什么不一样?

master是默认分支的通用名称。它不需要存在,但经常存在。

HEAD可以被认为是指向特定提交的变量。它可以更改并且与分支无关。

发出新的提交更改HEAD,检查任何更改HEAD


fetch 和 pull 和有什么不一样?

git pull [remote] [branch] 是相同的

git fetch [remote] [branch]
git merge [remote][/branch]

git pull --rebase [remote] [branch] 是相同的

git fetch [remote] [branch]
git rebase [remote][/branch]

Git .gitignore失效