Git 基本用法

基本用法

Git的三种主要状态

  • modified
    • 文件被修改,但还未被提交。
  • staged
    • 标记了一个已修改的文件,可以进入到下一个提交快照。
  • committed
    • 文件已经被安全的存放在本地数据库中。
  • 如果一个文件的某个版本已经在git directory中,则认为其是 committed。如果这个文件被修改后加入到了staging area,则其状态为 staged。如果这个文件被修改后没有被放入staging area,则其状态为modified。

Git项目的三个主要部分

  • working tree (working directory 工作区)
    • working tree是项目某个版本的签出,文件会从git directory的压缩数据库中抽取出来放到硬盘上供用户使用。
    • 工作区即在硬盘上看到的实际上的文件。
  • staging area (暂存区)
    • staging area是一个文件,通常包含在git directory中,包含了下次将要提交的信息。在技术上叫做"index"更合适,但"staging area"同样适用。
    • 暂存区通常保存通过git add命令加入的文件,在暂存区的文件会被提交。暂存区中的文件不一定和工作区的文件相同,通常适用于保存要提交的文件。
    • 暂存区的存在可以让用户灵活地进行提交,尤其是在对大量文件进行修改后,用户可以选择一些需要被提交的文件加入到暂存区,然后一起提交。
    • 暂存区位于.git/index,包含了将要提交的信息。
  • git directory (local respository 本地仓库)
    • git directory是Git存放项目元数据和对象数据库的位置,是Git中最重要的部分,并且当clone一个仓库时,克隆的就是它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Git的基本工作流程

  1. 在working tree中修改文件
  2. 选择那些想要加入下次提交的变化(文件),只添加那些变化到staging area中。
  3. 进行commit,将那些在staging area中的文件永久的存储在git directory中。

Git 设置

  • git使用git config命令来管理设置的变量,而这些变量会存储在3个不同的位置:

    • [path]/etc/gitconfig file

      • 系统级别的变量,会影响所有用户以及他们的仓库。在git config命令中添加–system选项,便可以从该文件中对变量进行读写。由于是系统级别的变量,因此需要管理员权限才可以操作。
    • ~/.gitconfig or ~/.config/git/config file

      • 用户级别的变量,只会影响当前用户的变量。可以通过添加–global选项来对变量进行读写,这会影响到当前用户下的所有仓库。
    • git directory中的config file(即.git/config)

      • 项目级别的变量,只会影响当前仓库。可以通过添加–local选项来对变量进行读写。不出意外,需要位于仓库中的某个位置才可以执行。
  • 每个config的级别都会覆盖之前的级别,即 .git/config的变量会覆盖掉[path]/etc/gitconfig中的变量。

  • 在winodws中,.gitconfig文件在C:\Users\$USER下,系统级别的存放在C:\ProgramData\Git\config下。

  • 通过以下命令可以看到设置的变量,以及变量的来源:

git config --list --show-origin

error: cannot spawn less: No such file or directory
...
file:"C:\\ProgramData/Git/config"       color.status=auto
file:"C:\\ProgramData/Git/config"       color.branch=auto
file:"C:\\ProgramData/Git/config"       color.interactive=true
...
file:C:/Development/Git/mingw64/etc/gitconfig   diff.astextplain.textconv=astextplain
file:C:/Development/Git/mingw64/etc/gitconfig   filter.lfs.clean=git-lfs clean -- %f
...
file:C:/Users/86155/.gitconfig  user.name=huangyezhou
file:C:/Users/86155/.gitconfig  user.email=2498144289@qq.com
file:C:/Users/86155/.gitconfig  
  • 由于可以设置不同级别的变量,所以可能会同时存在多个相同的变量,如果想要知道这个变量最终是由什么级别确定的可以执行以下命令:

    git config --show-origin <variable_name>
    # 这说明user.name是由当前项目文件决定的,即是一个项目级别的变量
    $ git config --show-origin user.name
    file:.git/config        lin
    # 说明user.email是由用户级别的配置文件决定的
    $ git config --show-origin user.email
    file:C:/Users/24981/.gitconfig  2498144289@qq.com
    

Git文件的生命周期

  • 每个在working directory的文件只有两种状态:tracked(追踪的)以及untracked(未追踪的)。被追踪的文件可以是上个快照中的文件,新的staged的文件,也可以是unmodified的文件,也可以是modified的文件,总而言之,被追踪的文件就是git知道的文件。未被追踪的文件就是其它情况的文件:不是上个快照中的文件,也不在staging area中的文件。当刚开始克隆一个仓库后,所有的文件都是被追踪的并且是unmodified,因为git刚刚将它们检出并且没有进行任何修改。

  • 当修改一个提交过的文件时,git将它们视为modified。在实际工作中,可以有选择地存储这些modified文件,并提交存储,然后不断循环。

  • 总的来说,git中的文件有很多类型

    • 未被追踪的文件(Untracked Files):
      • 这些是工作目录中存在的文件,但Git尚未开始跟踪。它们没有被包含在以前的提交中,也没有被加入到暂存区。
      • 例如,新创建的文件在被git add之前都是未追踪的。
      • 之所以会存在未被追踪的文件,是因为在实际开发过程中,会出现一些中间文件,例如.class文件,.o文件等。如果文件都同统一被追踪的话,那么整个git仓库的大小就会变大。因此,开始是未追踪的状态方便用户选择哪些文件是需要被
    • 追踪的文件(Tracked Files):
      • 这些文件在之前的提交中已经被Git记录过,Git知道它们的存在。
      • 追踪的文件可以是未修改的(未改变),修改的(已改变但未暂存),或者已暂存的。
    • 修改但未暂存的文件(Modified but Unstaged Files):
      • 这些是被Git追踪的文件,但自上次提交以来已经被修改了,并且还没有被添加到暂存区。
      • 这些更改只存在于工作目录中。
    • 暂存的文件(Staged Files):
      • 这些文件在工作目录中被修改过,并且已经被加入到暂存区,准备下一次提交。
      • 暂存的文件将被包括在下一次git commit操作中。
    • 已提交的文件(Committed Files):
      • 这些文件的当前快照已经存储在仓库的历史记录中。
      • 一旦文件被提交,它就会从暂存区移除,并且其状态会更新为未修改。
    • 冲突的文件(Conflicted Files):
      • 在合并操作期间,如果同一个文件在不同的分支上有不同的更改,Git可能无法自动合并这些更改,这会导致冲突。
      • 冲突的文件需要手动解决,然后将其标记为已解决并提交解决后的版本。

    使用git status命令,你可以查看工作目录和暂存区中文件的当前状态,这有助于理解哪些文件是未跟踪的、哪些已修改但未暂存、哪些已暂存等。了解这些不同的文件状态对于有效地使用Git进行版本控制至关重要。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 例如,将一个未被追踪的文件通过了git add命令后,会变为一个被追踪的、暂存的、未被修改的文件。

暂存区的内容

  • 当使用git add命令时,文件总是会变为被跟踪的,并且也会保存文件的变化到暂存区。即暂存区保存了文件在git add时的状态,也保存了文件的变化。
  • 当使用git commit时,暂存区只是将文件的变化提交给了仓库,因此当提交后,再使用git status时,会发现没有暂存区相关的输出。但文件的状态仍然保留着,这也就意味着,当使用git diff时,工作区的文件会和暂存区中的文件进行比较。git ls-files --cached也能打印出已经被追踪的文件的信息。

查看文件状态

  • 查询文件状态的命令为 git status,当在一个刚克隆或者刚创建的仓库中(my_dir/git_hello)执行该命令,将会显示:

    $ git status
    On branch master
    
    No commits yet
    
    nothing to commit (create/copy files and use "git add" to track)
    
  • 这表明没有任何被追踪的文件被修改过,同时也没有任何未被追踪的文件。并且该命令告知了我们当前所处的branch。

  • 如果添加一个之前不存在文件,再次输入git status,将会显示:

    $ echo 'My Project' > README
    $ git status
    On branch master
    
    No commits yet
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
            README
    
    nothing added to commit but untracked files present (use "git add" to track)
    
  • 我们可以看到,新的文件README是未被追踪的,因为它位于"Untracked files"条目下。这种未被追踪的文件通常意味着git没有在之前的快照中见到过,即该文件从未被提交过并且也不在staged状态。git不会一开始就将其将入到要commit的快照中,除非用户明确地指定该行为,这是为了防止用户意外地将一些二进制文件以及生成的日志文件加入进去。

  • 如果想要明确地追踪一个文件,需要使用git add

    $ git add README
    $ git status
    On branch master
    
    No commits yet
    
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
    
            new file:   README
    
    
  • 我们可以看到README文件已经变为了staged状态,因为其在"Changes to be committed"条目下,如果此时执行commit操作,该文件版本将被加入到后续的历史快照中(即此后的各个版本的快照均能找到该版本的文件,在该文件不被修改的情况下)。git add命令后跟文件名或目录名,若是目录名,则git会递归地将目录下的所有文件进行追踪。

  • 接下来让我们修改已经追踪过的文件:首先需要新建一个名为CONTRIBUTING.md的文件,追踪该文件,然后修改该文件。

    $ echo 'A little contribution' > CONTRIBUTION.md
    $ git add CONTRIBUTION.md
    $ echo 'Edit it' > CONTRIBUTION.md
    $ git status
    On branch master
    
    No commits yet
    
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
    
            new file:   CONTRIBUTION.md
            new file:   README
    
    Changes 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:   CONTRIBUTION.md
    
    
  • 我们可以看到CONTRIBUTION.md同时出现在了"Changes to be committed"以及"Changes not staged for commit",这说明该文件同时处在两个状态:“被追踪且处于staged状态”以及“被追踪且处于modified”状态。这是两个矛盾的状态,如果此时输入git commit命令,那么使用git add命令追踪过的文件会被提交,而被修改的文件则不会。如果使用git add命令后又修改了文件,那么只需要再使用一次git add命令即可。让我们在不执行add的情况下进行提交来看一下:

$ git commit -m "CONTRIBUTION.md in not staged"
$ git status
On branch master
Changes 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:   CONTRIBUTION.md

$ cat CONTRIBUTION.md
Edit it
  • 我们可以看到,提交后,CONTRIBUTION.md仍处于unstaged(modified)状态,相当于我们对上个版本快照中CONTRIBUTION.md文件进行了修改但还未添加进storaging area。所以我们可以看到git add命令的实际作用是将当前文件的版本加入到storaging area,而不是将这个文件加入到storaging area。
  • 直接使用git status得到的输出较为冗长,在该命令后加-s 或 --short选项可以得到更为简洁的输出表示。
$ git status -s
 M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
  • 新建的未被追踪的文件前会有’??‘,而新建的被加入staging area的文件前将会有’A’,修改过的文件前会有’M’。可以看到,文件前有两列输出,左边的列表示staging area的状态,右列的表示working directory的状态。以上述输出为例:README文件状态为在working directory被更改,但未加入staging area。lib/simplegit.rb被更改且加入了staging area。Rakefile被更改然后被staged,然后又被更改,因此状态会同时出现在staged以及unstaged。
  • 如果将CONTRIBUTION.md的内容修改为’a’,然后加入到storaging area,接着修改内容为’b’,再将内容改回为’a’,git的状态会是什么?(主要为了观察文件的状态是因为修改文件这个动作而产生变化,而是因为文件内容而产生变化)
$ git status -s
M  CONTRIBUTION.md
(base)
86155@LAPTOP-R32U2085 MINGW64 /e/Github_Pro/git_hello (master)
$ vim CONTRIBUTION.md
(base)
86155@LAPTOP-R32U2085 MINGW64 /e/Github_Pro/git_hello (master)
$ git status -s
MM CONTRIBUTION.md
(base)
86155@LAPTOP-R32U2085 MINGW64 /e/Github_Pro/git_hello (master)
$ vim CONTRIBUTION.md
(base)
86155@LAPTOP-R32U2085 MINGW64 /e/Github_Pro/git_hello (master)
$ git status -s
M  CONTRIBUTION.md
  • 可以看到,将’a’修改为’b’,git将其状态修改为了MM,说明git捕捉到了工作区文件的变化,接着再将’b’改回’a’,git将其状态修改为了’M’,说明git是根据文件内容来判断文件是否修改的,而不是通过修改这个动作。也就是说,就算对文件不停修改,只要最后内容和原来的一样,git依然认为文件没有被修改。

忽略文件

  • 在实际工作中,我们可能不希望某些文件出现在状态区中,例如二进制文件以及日志文件。通过创建.gitignore文件在其写入希望忽略的文件或文件匹配模式即可忽略这些文件。
  • .gitignore文件遵循着以下规则:
    • 空白行或是以’#'开头的行会被忽略
    • 全局匹配模式会工作,匹配模式对递归地适用到工作区中
      • 全局匹配模式与shell使用的简化正则表达式相似,一个星花(*)匹配0至多个字符,[abc]匹配方括号内任意一字符,问号(?)匹配一个字符,[0-9]匹配在0至9之间的数字。还可以使用两个星号来匹配嵌套目录, a/**/z 将匹配 a/z, a/b/z, a/b/c/z。
    • 以斜线’/'开头的pattern会忽略递归模式
    • 以斜线’/'结尾的pattern特指一个目录
    • 以惊叹号’!'开头来否认一个pattern
# ignore all .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in any directory named build
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf

详细查看staged及unstaged的改变

  • 使用git status可以看到文件状态的变化,但是想要看到文件的内容有哪些变化则需要使用git diff命令。
  • 这里假设我们已经将README文件进行暂存,然后对CONTRIBUTION.md文件进行修改,并不暂存它。此时使用git status命令,将会看到:
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   README

Changes 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:   CONTRIBUTION.md

  • 使用git diff命令(不加任何参数的情况下比较的是工作区和暂存区之间的差异)将会看到
$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.
 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's
  • 第一行diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md的a版本CONTRIBUTION.md为改动前的版本,b版本的CONTRIBUTION.md为改动后的版本。
  • 第二行index 8ebb991..643e24f 100644,index后面的两个数字表示两个文件的hash值,暂存区的8ebb991对象与工作区的643e24f 对象进行比较,最后的6位数字是对象的模式(100表示普通文件,644表示权限)。
  • 第三行以及第四行表示进行比较的两个文件--- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md---表示变动前的版本,+++表示变动后的版本。
  • 第四行@@ -65,7 +65,8 @@分为两个部分,第一个部分是-65,7-表示修改前,65,7表示第65行开始的7行,后面的+65,8+表示修改后,65,8表示65行开始的8行。这说明修改前的65行开始的7行中发生了改变,最终变味了修改后的65行开始的8行。
  • 剩下的是比较信息
    • 行前面有-+,以及什么都没有,分别表示删、增、无变动。
    • -表示减少的部分。
    • +表示增加的部分。
    • 从上数输出中可以看出,修改后的文件是将修改前的文件中的merged in删除,然后增加了merged in. Also, split your changes into comprehensive chunks if your patch is以及longer than a dozen lines.,这也是为什么是从65,7变为65,8的原因。
  • 该命令比较的是工作区文件以及暂存区文件的差异,输出的结果告诉了我们做了哪些修改但还没有加入到暂存区。
  • 如果想要比较暂存区和上一次提交的区别,可以使用git diff --staged (--cached) ,将会显示:
$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+My Project

提交

  • 当我们需要将我们修改的文件提交到版本库时,需要执行git commit。值得注意的是,没有被git add添加到暂存区的文件依然会留在工作区,不会被提交到版本库。所以,在提交之前,需要再使用一次git status命令来查看是否存在修改但未添加到暂存区的文件。使用git commit -m后跟需要提交的信息即可提交。

跳过Staging area

  • 通常情况下,我们进行一次提交,需要先使用git add命令将文件加入暂存区,再执行git commit命令提交暂存区的文件。如果希望跳过staging area, 可以使用git commit -a -m命令将所有追踪的文件进行提交,如下所示:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes 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: CONTRIBUTING.md
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'Add new benchmarks'
[master 83e38c7] Add new benchmarks
 1 file changed, 5 insertions(+), 0 deletions(-)

移除文件

  • 如果只是使用rm命令移除文件,文件仍然处于追踪状态,因此会显示:
$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
  deleted: PROJECTS.md
no changes added to commit (use "git add" and/or "git commit -a")
  • 使用git rm命令将会先将其处于未追踪状态,然后将其从硬盘移除。如果该文件被修改过,或已经处于暂存区,那么需要添加-f选项来进行安全移除。
  • 另一个有用的东西就是只想将其从暂存区移除而不将其从硬盘移除,即将文件改为未追踪状态,使用命令git rm --cached

移动文件

  • 使用git mv命令来移动文件,其相当于同时执行3个命令$ mv README.md README $ git rm README.md $ git add README,即先在硬盘中将文件进行移动,然后将原始文件从暂存区中移除,再将新的文件加入暂存区。如果不是使用该命令进行移动文件,那么需要手动地输入git add以及git rm(似乎都使用git add也可以)命令来对暂存区进行处理。

浏览提交历史

  • 最基础也是最强大的命令是git log,执行该命令可以看到:
$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
  Change version number
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
  Remove unnecessary test
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
  Initial commit
  • 选项-p--patch将会展示每次提交之间的差异,同时也可以限制输出的条目数量:
$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
  Change version number
diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
  s.platform = Gem::Platform::RUBY
  s.name = "simplegit"
- s.version = "0.1.0"
+ s.version = "0.1.1"
  s.author = "Scott Chacon"
  s.email = "schacon@gee-mail.com"
  s.summary = "A simple gem for using Git in Ruby code."
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
  Remove unnecessary test
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
  end
 end
-
-if $0 == __FILE__
- git = SimpleGit.new
- puts git.show
-end
  • 如果想要查看每次提交的变化的简要概述,可以使用git log --stat,如下所示:
$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
  Change version number
 Rakefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
  Remove unnecessary test
 lib/simplegit.rb | 5 -----
 1 file changed, 5 deletions(-)
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
  Initial commit
 README | 6 ++++++
 Rakefile | 23 +++++++++++++++++++++++
 lib/simplegit.rb | 25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)
  • 另一个很实用的选项是--pretty,该选项可以修改日志输出的格式,如值为oneline可以将每次提交信息都输出在一行中,此外值还可以选择shortfull以及fuller
$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 Change version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Remove unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 Initial commit
  • 选项的值为format时可以自定义输出的格式:
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : Change version number
085bb3b - Scott Chacon, 6 years ago : Remove unnecessary test
a11bef0 - Scott Chacon, 6 years ago : Initial commit
  • 更多format值如下图所示:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • oneline以及foramt选项与--graph选项结合将会变得更加强大,该选项能够显示项目分支的创建和合并情况:

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 Ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Add method for getting the current branch
* | 30e367c Timeout code and tests
* | 5a09431 Add timeout protection to grit
* | e1193f8 Support for heads with slashes in them
|/
* d6016bc Require time for xmlschema
* 11d191e Merge branch 'defunkt' into local

过滤日志输出

  • 通常情况下git log会打印出所有提交的信息,而通常我们可能只需要特定的某些信息。
  • --grep选项可以帮助过滤出commit信息中包含关键词的提交。
  • -S选项可以过滤出修改的文件中包含增删某字符串的提交。
  • -- path/file选项可以过滤出针对某文件的提交。

撤销操作

  • 在某些情况下,我们需要撤销一些之前做过的操作,但执行撤销操作要小心,因为我们不能总是撤销我们做过的“撤销”操作。
  • 当我们过早地进行了提交操作忘记添加某些文件或是填写错误提交信息时,我们希望能够重新进行一次提交,此时可以使用git commit --amend命令,该命令获取暂存区信息进行提交,如果自上次提交后,暂存区没有任何变化,那么该命令执行后将会看到和上次一样的快照以及提交信息。如果在提交后忘记添加某些文件,那么操作应该为:
$ git commit -m 'Initial commit'
$ git add forgotten_file
$ git commit --amend
  • 第二次的提交信息将会替换第一次的提交信息,就像第一次的提交根本不存在一样。该命令只会将本地的还未提交的修改进行提交。
  • 如果我们想对暂存区以及工作区进行的操作进行撤销,那么git status命令的输出结果就已经给了我们提示:
$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
  renamed: README.md -> README
  modified: CONTRIBUTING.md
  • 我们可以看到使用git reset HEAD <file>… 可以取消stage操作。
$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
  renamed: README.md -> README
Changes 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: CONTRIBUTING.md
  • 可以看到,文件CONTRIBUTION.md已经变为了未暂存状态,但是这个命令是一个危险的命令,但是由于工作区的文件并没有进行更改,因此还是相对安全的。
  • 如果我们想将工作区中修改的文件恢复到未修改的状态,git status命令也给了我们提示:
Changes 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: CONTRIBUTING.md
  • 使用git checkout -- <file>...即可:
$ git checkout -- CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
  renamed: README.md -> README
  • 可以看到变化已经被撤销,该命令也是一个危险的命令,因为使用了该命令后,本地文件发生的变化将全部被撤销,除非明确地知道永远不会使用修改后的文件,否则不要使用该命令。因为,任何提交到git版本库的文件都会被保存起来,即使是后面这些文件被删除或整个提交以及分支被删除,git仍然能够恢复这些,但是在工作区(未进行提交)进行的操作永远无法再现了。所以,如果希望将文件的变化撤销,但又想保存这些变化以备不时之需,那么就需要使用分支来解决。

HEAD detached(分离的HEAD)

  • 在使用git reset跳转到某一个版本时,会处于HEAD detached 状态,在这个状态下修改后直接提交,会让提交到一个悬空的detached的版本,即没有任何分支和其对应,而是到了一个独立的空间中。

    # 当前分支有很多提交版本
    $ git log --pretty=oneline
    0e77028a107012934a66a426f19e9e58a4cdb3bc (HEAD -> main) dula
    3a5a878b61f31c5c0bf76d1d29bd3a6b90af6698 good
    958787e71f337ef306e54ea2a356bb981f49de30 sixth commit
    07a508e095502f0b2e3612304565c8b647b4f726 fifth commit
    81e1219bff62492336ac99862d330b71a6260d58 fourth commit
    8e78cac802ba2223e4b5ee08f4aeac49697df113 (tag: v0.9) third commit
    bfd3765faaa3de9f4007c76cb9bf7bea35a69484 second commit
    e5818fc8455268dd353711cdc66820bab511fcfd first commit
    
    
    # 切换到之前提交的一个版本,系统也会提示进入到了一个detached HEAD
    $ git checkout 07a508
    Note: switching to '07a508'.
    
    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 switching back to a branch.
    
    If you want to create a new branch to retain commits you create, you may
    do so (now or later) by using -c with the switch command. Example:
    
      git switch -c <new-branch-name>
    
    Or undo this operation with:
    
      git switch -
    
    Turn off this advice by setting config variable advice.detachedHead to false
    
    HEAD is now at 07a508e fifth commit
    
    # 查看当前分支,发现状态确实是HEAD detached
    git branch
    * (HEAD detached at 07a508e)
    
    # 对当前版本进行修改并提交
    $ vi p.txt
    $ git add *
    $ git log --pretty=oneline
    07a508e095502f0b2e3612304565c8b647b4f726 (HEAD) fifth commit
    81e1219bff62492336ac99862d330b71a6260d58 fourth commit
    8e78cac802ba2223e4b5ee08f4aeac49697df113 (tag: v0.9) third commit
    bfd3765faaa3de9f4007c76cb9bf7bea35a69484 second commit
    e5818fc8455268dd353711cdc66820bab511fcfd first commit
    
    $ git commit -m "detached HEAD"
    [detached HEAD 5c470a5] detached HEAD
     1 file changed, 1 insertion(+)
     create mode 100644 p.txt
    
    # 出现了新版本5c470a57418ed1a6446248b62b952947b36525f1
    $ git log --pretty=oneline
    5c470a57418ed1a6446248b62b952947b36525f1 (HEAD) detached HEAD
    07a508e095502f0b2e3612304565c8b647b4f726 fifth commit
    81e1219bff62492336ac99862d330b71a6260d58 fourth commit
    8e78cac802ba2223e4b5ee08f4aeac49697df113 (tag: v0.9) third commit
    bfd3765faaa3de9f4007c76cb9bf7bea35a69484 second commit
    e5818fc8455268dd353711cdc66820bab511fcfd first commit
    
    # 将分支切换到原本的分支,即之前的版本,发现系统也会提示如果想保留detached HEAD,最好是新建一个分支
    $ git switch main
    Warning: you are leaving 1 commit behind, not connected to
    any of your branches:
    
      5c470a5 detached HEAD
    
    If you want to keep it by creating a new branch, this may be a good time
    to do so with:
    
     git branch <new-branch-name> 5c470a5
    
    # 查看log信息,发现没有detached HEAD的版本
    $ git log --pretty=oneline
    0e77028a107012934a66a426f19e9e58a4cdb3bc (HEAD -> main) dula
    3a5a878b61f31c5c0bf76d1d29bd3a6b90af6698 good
    958787e71f337ef306e54ea2a356bb981f49de30 sixth commit
    07a508e095502f0b2e3612304565c8b647b4f726 fifth commit
    81e1219bff62492336ac99862d330b71a6260d58 fourth commit
    8e78cac802ba2223e4b5ee08f4aeac49697df113 (tag: v0.9) third commit
    bfd3765faaa3de9f4007c76cb9bf7bea35a69484 second commit
    e5818fc8455268dd353711cdc66820bab511fcfd first commit
    
    

远程工作

  • 为了能够与他人使用git进行合作或只是将项目存放在某个地方,就需要使用远程仓库。

  • 使用git remote命令便可以查看当前已经配置的远程仓库,如果已经克隆了一个仓库,那么至少是可以看到名为origin的远程仓库。

  $ git clone https://github.com/schacon/ticgit
  Cloning into 'ticgit'...
  remote: Reusing existing pack: 1857, done.
  remote: Total 1857 (delta 0), reused 0 (delta 0)
  Receiving objects: 100% (1857/1857), 374.35 KiB | 268.00 KiB/s, done.
  Resolving deltas: 100% (772/772), done.
  Checking connectivity... done.
  $ cd ticgit
  $ git remote
  origin
  • 使用-v选项可以看到用于读写的远程库简称后对应的URLS:

    $ git remote -v
    origin https://github.com/schacon/ticgit (fetch)
    origin https://github.com/schacon/ticgit (push)
    
  • 添加一个远程仓库可以使用git remote add <shortname> <url>

    $ git remote
    origin
    $ git remote add pb https://github.com/paulboone/ticgit
    $ git remote -v
    origin https://github.com/schacon/ticgit (fetch)
    origin https://github.com/schacon/ticgit (push)
    pb https://github.com/paulboone/ticgit (fetch)
    pb https://github.com/paulboone/ticgit (push)
    
  • 如果想要获取远程仓库拥有但本地仓库还未拥有的信息,可以使用git fetch <shortname>命令:

    $ git fetch pb
    remote: Counting objects: 43, done.
    remote: Compressing objects: 100% (36/36), done.
    remote: Total 43 (delta 10), reused 31 (delta 5)
    Unpacking objects: 100% (43/43), done.
    From https://github.com/paulboone/ticgit
     * [new branch] master -> pb/master
     * [new branch] ticgit -> pb/ticgit
    

标签

​ 标签可以给特定的版本进行标记,可以直接使用git tag命令打印出当前的所有版本。

  • 创建标签的方式有两种:lightweight以及annotated,其中annotated会包含更多的信息

    • 使用 git tag <tag_name> 创建lightweight的tag, 使用git tag -a <tag_name> -m <commit_message>创建annotated的tag,使用git show <tag_name>查看tag信息
    # lightweight
    git tag v1.3
    git show v1.3
    commit 67442a179ec67c81af2c471069d1c3e96d85937e (HEAD -> main, tag: v1.3, tag: v1.2, tag: v1.1)
    Author: JinFish <2498144289@qq.com>
    Date:   Fri Jan 26 11:15:55 2024 +0800
    
    # annotated
    git tag -a v1.4 -m "g"
    $ git show v1.4
    tag v1.4
    Tagger: JinFish <2498144289@qq.com>
    Date:   Fri Jan 26 11:25:19 2024 +0800
    
    g
    
    commit 67442a179ec67c81af2c471069d1c3e96d85937e (HEAD -> main, tag: v1.4, tag: v1.3, tag: v1.2, tag: v1.1)
    Author: JinFish <2498144289@qq.com>
    Date:   Fri Jan 26 11:15:55 2024 +0800
    
    
    • 还可使用git tag <tag_name> <hash>为指定版本添加tag。

    • 默认情况下,在本地添加tag后,不会影响到远程库,为了将本地tag的变化提交到远程库,可以使用git push origin <tag_name>进行提交,或者使用git push origin --tags将所有的tag提交到远程。

      git push origin v1.1
      Enumerating objects: 5, done.
      Counting objects: 100% (5/5), done.
      Delta compression using up to 16 threads
      Compressing objects: 100% (2/2), done.
      Writing objects: 100% (3/3), 316 bytes | 79.00 KiB/s, done.
      Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
      To github.com:JinFish/git_test.gitgi
       * [new tag]         v1.1 -> v1.1
       
      git push origin --tags
      Enumerating objects: 3, done.
      Counting objects: 100% (3/3), done.
      Delta compression using up to 16 threads
      Compressing objects: 100% (3/3), done.
      Writing objects: 100% (3/3), 318 bytes | 159.00 KiB/s, done.
      Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
      remote: Resolving deltas: 100% (1/1), done.
      To github.com:JinFish/git_test.git
       * [new tag]         v0.9 -> v0.9
       * [new tag]         v1.0 -> v1.0
       * [new tag]         v1.2 -> v1.2
       * [new tag]         v1.3 -> v1.3
       * [new tag]         v1.4 -> v1.4
      

checkout 发生了什么

​ checkout即检出某个版本,可以是当前分支上的某个版本,也可以是另外分支上的一个版本,实际上切换分支肯定是会切换版本的。当checkout到某个版本时,例如版本a,会将版本a中对应的文件替换到工作区,即当前工作区的文件会变为版本a中的文件,并且暂存区也会变为版本对应的暂存区,这里的暂存区只会有对文件的跟踪,不再有版本的变化。因为检出的版本是已经提交过的,提交时会将变化提交到仓库,即当时提交的时候暂存区的变化会被清空,因此检出时暂存区也不会保留变化。

​ 如果checkout前工作区和暂存区已经进行了改动,那么情况会稍有不同。当我们提交了一个版本后继续进行更改,工作区和暂存区可能都会发生变化,然而由于我们没有提交,目前在修改的版本实际上不属于任何分支,也不是任何版本。此时,如果我们切换到a版本,工作区和暂存区的变化也会随之到a版本。就像在a版本上进行修改一样。如果我们的更改没有和a版本有冲突,例如新建了a版本不存在的文件,那么便可以切换。但是如果我们的更改和a版本有冲突,那么则可能不会成功切换到那个版本或分支。

  # 创建了一个所有版本都不存在的文件 b.txt
  $ git status
  On branch testing
  Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
          new file:   b.txt
  
  # 切换到main分支,可以看到main分支将修改视为本分支的修改
  $ git checkout main
  Switched to branch 'main'
  A       b.txt
  Your branch is ahead of 'origin/main' by 2 commits.
    (use "git push" to publish your local commits)
  
  24981@Thinkbook_huang MINGW64 /d/Applications/Typora/git_test (main)
  $ git status -s
  A  b.txt
  
  # main分支可以成功提交
  $ git commit -m "ok"
  [main 0f6344e] ok
   1 file changed, 1 insertion(+)
   create mode 100644 b.txt
   
  # 此时testing中的修改便消失了,因为main分支已经提交了
  $ git checkout testing
  Switched to branch 'testing'
  $ git status -s
  None
  
  # 如果进行的修改与要被checkout的版本有冲突,那么则不能chekcout
  $ vi a.txt
  $ git checkout main
  error: Your local changes to the following files would be overwritten by checkout:
          a.txt
  Please commit your changes or stash them before you switch branches.
  Aborting

​ 注意:如果工作区和暂存区没有提交就切换到a版本,则将视为在a版本进行了工作区和暂存区的修改,提交后的版本也是在a版本之后的。因此,安全起见,在切换分支和版本之前,最好将工作区和暂存区的修改进行提交。

分支与合并

当我们想创建一个分支时,我们可以使用git branch <branch_name>命令创建一个新的分支,即一个新的指针指向当前版本,但执行该命令后并不会切换分支,只是创建了一个分支:

git branch testing

# 当前HEAD在main分支上
$ git log --oneline -2
32abca6 (HEAD -> main, origin/main, testing) Merge branch 'main' of github.com:JinFish/git_test
add87a2 akdfj

  • 当想要切换到另外一个分支上时,可以使用git checkout <branch_name>

    $ git checkout testing
    Switched to branch 'testing'
    
  • checkout发生了什么叙述的那样。如果切换后更改和分支出现冲突,那么将不能切换分支。

  • 创建和切换分支的命令还有:

    • git checkout -b <branch_name>:创建并切换到新分支;
    • git checkout以及git switch后跟<branch_name>:切换到一个已经存在的分支;
    • git switch -c <branch_name>:创建并切换到新分支;
    • git switch -:回到切换之前的分支;
    • git branch:查看当前所有的分支,以及HEAD所在的分支;
  • 合并分支的命令是git merge <branch_name>,在当前分支上将某个分支上的内容合并:

    • 如果被合并的分支的父节点是当前分支,那么git会将当前分支的指针直接移到合并的分支:

      # 178ba7b原本是从0f6344创建的main2分支,通过git merge合并后,main和mian2的指针均指向178ba7b
      $ git log --graph --pretty=oneline
      * 178ba7bd046f69572ada55ab23fc8b3b9cdd205c (HEAD -> main, main2) ok
      * 0f6344ee601388b3975c74380e0fcea766d0de38 ok
      
    • 如果当前分支和合并的分支没有父子关系,那么将会创建一个新的版本,这个版本会指向两个分支,即这两个分支都是该提交的父节点

      # 可以看到f5148是由178ba7bd0以及beab84fd55合并得到的
      $ git log --graph --pretty=oneline
      *   f51488c831488a2d522da9ead9033003b9a3a0f4 (HEAD -> main) oookk
      |\
      | * beab84fd55fecb64625e79a8ed993ced09e67332 ok
      | * 62638a53426586d34b77378d5acc6beed3d4fa07 ok
      | * dc68d1cebd0e4acf2f5d883f4457545a62381f6d testing
      * | 178ba7bd046f69572ada55ab23fc8b3b9cdd205c ok
      
      
    • 合并可能会出现冲突,根据提示将出现冲突的文件进行手动处理即可。

  • 如果想要删除分支,那么可以使用git branch -d <branch_name>命令,只会删除分支名称,不会删除其已经存在的版本:

    $ git branch -d main2
    Deleted branch main2 (was 178ba7b).
    
    # 可以看到178ba7b仍然存在,只有main仍然指向该版本,而main2已经被删除掉了
    $ git log --graph --pretty=oneline
    * 178ba7b
    178ba7b仍然存在d046f69572ada55ab23fc8b3b9cdd205c (HEAD -> main) ok
    
  • 使用git branch --all可以看到所有的分支,包括远程分支(后续补充远程分支的概念):

    $ git branch --all
    * main
      remotes/origin/main
    

远程分支

​ 远程分支和本地分支实际上是独立的,并不是远程仓库的分支和本地仓库的分支是共用的。如果在本地创建一个仓库,默认是没有远程分支的,只有设置好远程库,并进行一次提交之后,才会有远程分支。

# 在一个新建的本地仓库中,只有master这一初始的分支
$ git branch -a
* master

# 添加上远程库之后也是没有远程分支信息
$ git remote add origin git@github.com:JinFish/git_test2.git
$ git branch -a
* master

# 尝试提交到origin,报错:说当前的branch没有对应的upstream branch,即对应的远程分支
$ git push origin
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master
    
# 该命令显式地指定了提交的远程库,因此可以成功,但是不会建立本地仓库和远程仓库之间的关系,即随后不能使用git push直接提交
$ git push origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 203 bytes | 203.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:JinFish/git_test2.git

# 使用-u命令可以建立起本地分支和远程分支的对应关系
$ git push -u origin master
 * [new branch]      master -> master
 

​ 当有了远程分支之后,执行git push即可,git已经为本地分支和远程分支建立起了关系

# 可以看到本地的master分支和远程的master分支建立起了联系
$ git branch -vv
* master 59636c6 [origin/master] 4

# 随后执行git push即可,master分支会自动上传到远程的master分支
$ git push
Everything up-to-date

​ 注意:在上游(远程)分支名和本地分支名相同的情况下,通常不会有错误。但是当名称不同的情况下,直接使用git push可能会报错,因为在git中的配置变量push.default默认值为simple,这要求本地分支名和远程分支名相同时,git push才会将本地分支推送到远程分支。所以尽量保证本地的分支名和远程库分支名相同,避免额外的意外发生。

  • 使用git branch -a命令可以查看所有的分支,包括远程分支,使用git branch -vv可以查看本地分支和远程分支之间的对应关系。

    $ git branch -a
    * master
      t2
      testing
      remotes/origin/main
      remotes/origin/master
      remotes/origin/t2
      remotes/origin/testing
    
    $ git branch -vv
    * master  59636c6 [origin/master] 4
      t2      c7e4e00 [origin/t2] ok
      testing c7e4e00 [origin/testing] ok
    
    
  • 我们本地仓库也会有远程分支的引用,但是本地的远程分支不一定和远程的是同步的。当使用git pull=git fetch + git mergegit fetch,以及git push的时候,远程分支会进行更新:

    # 切换到main分支,进行了新的提交
    $ git log --pretty=oneline
    ea823edbf2fbcb6de20eaab6422454453234af04 (HEAD -> main) 5
    59636c62f07fa88d71971cd8024aace537a8c540 (origin/master, origin/main, master) 4
    d667ef3777b9ab4965e16a51f380f3e2fbb74703 skdfj
    
    # 切换到origin/mainr分支,并没有发现对应的提交,说明main和origin/main是独立的
    $ git log --pretty=oneline
    59636c62f07fa88d71971cd8024aace537a8c540 (HEAD, origin/master, origin/main, master) 4
    d667ef3777b9ab4965e16a51f380f3e2fbb74703 skdfj
    a108cdea96d1f97a20f82bad3ffd83a112ac21f1 3
    74508117eb99fe52d47dd5084332220bae0855c7 sk
    7bb66f0fe9759bac901d12f7f2ac0aaafebd352a first
    
    # 再切换到origin/main,发现origin/main的版本更新了,说明git push会同步本地库中的远程分支和远程库中的远程分支
    $ git log --pretty=oneline
    ea823edbf2fbcb6de20eaab6422454453234af04 (HEAD, origin/main, main) 5
    59636c62f07fa88d71971cd8024aace537a8c540 (origin/master, master) 4
    
    
    # 当前本地origin/main版本还是原始版本
    $ git log --pretty=oneline
    ea823edbf2fbcb6de20eaab6422454453234af04 (HEAD, origin/main, main) 5
    59636c62f07fa88d71971cd8024aace537a8c540 (origin/master, master) 4
    
    # 在远程库进行了提交之后,拉取远程库,本地的远程库有了更新
    $ git fetch
    remote: Enumerating objects: 4, done.
    remote: Counting objects: 100% (4/4), done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
    Unpacking objects: 100% (3/3), 924 bytes | 92.00 KiB/s, done.
    From github.com:JinFish/git_test2
       ea823ed..592ab30  main       -> origin/main
       
    $ git checkout origin/main
    Previous HEAD position was ea823ed 5
    HEAD is now at 592ab30 Create rr.txt
    
    # 但是本地的main分支没有被更新
    $ git log --pretty=oneline
    ea823edbf2fbcb6de20eaab6422454453234af04 (HEAD -> main) 5
    59636c62f07fa88d71971cd8024aace537a8c540 (origin/master, master) 4
    
    # 进行merge后便有了更新
    $ git merge
    Updating ea823ed..592ab30
    Fast-forward
     rr.txt | 1 +
     1 file changed, 1 insertion(+)
     create mode 100644 rr.txt
    $ git log --pretty=oneline
    592ab30b36c2c42ddca29fdfe5e37fdb36cb38dc (HEAD -> main, origin/main) Create rr.txt
    ea823edbf2fbcb6de20eaab6422454453234af04 5
    59636c62f07fa88d71971cd8024aace537a8c540 (origin/master, master) 4
    
    

版本选择

​ 跳转到某个版本的命令可以使用git checkout以及git reset,但是二者之间有着一些区别:

  • git checkout跳转的版本会在一个detached的HEAD上,即在上面做的任何更改都不会影响到原来的分支,而使用git reset可能会在原本的分支上添加额外的提交:

    # 当前版本的状态
    $ git status -s
     M a.txt
    A  yui.txt
    ?? yut.txt
    
    
    # 使用checkout到某固定版本
    $ git checkout 7bb66f0fe9759bac901d12f7f2ac0aaafebd352a
    Note: switching to '7bb66f0fe9759bac901d12f7f2ac0aaafebd352a'.
    
    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 switching back to a branch.
    
    # 发现原来版本的工作区和缓存区的状态被保留,并且处于一个分离的分支
    $ git status -s
     M a.txt
    A  yui.txt
    ?? yut.txt
    
    $ git branch
    * (HEAD detached at 7bb66f0)
      main
      master
      t2
      t3
      testing
    
  • git checkout会保留原始版本工作区和暂存区的变化,而git reset则会显示版本之间的变化,不仅是原始版本发生的变化,还有两个版本之间的变化,具体有哪些变化和git reset的三个参数有关:

    • --hard:将当前分支的头指针、索引(暂存区)和工作目录都重置为指定的提交状态。这个参数不会显示版本之间的变化,也不会显示原始版本发生的变化,即使用git status -s不会看到任何输出。

      $ git reset --hard 7bb66f0fe9759bac901d12f7f2ac0aaafebd352a
      HEAD is now at 7bb66f0 first
      
      # 只有未被追踪的文件的状态被保留,原始工作区和缓存区的状态不被保留,并且也处于main分支上
      $ git status -s
      ?? yut.txt
      
      $ git branch
      * main
        master
        t2
        t3
        testing
      
      # 切回原始版本,发现原始版本工作区的变化和缓存区的变化消失
      $ git reset --hard b0be1ac
      HEAD is now at b0be1ac ok
      $ git status -s
      ?? yut.txt
      
    • --soft:这个命令将当前分支的头指针移动到指定的提交,但不改变索引(暂存区)和工作目录。因此,跳转到某个版本后,工作区和暂存区还是原始版本的。

      $ git reset --soft 7bb66f0fe9759bac901d12f7f2ac0aaafebd352a
      # 版本之间的差异会显示出来,以及工作区和缓存区的变化
      $ git status -s
      A  b.txt
      A  c.txt
      A  d.txt
      A  e.txt
      A  s.txt
      ?? yut.txt
      
    • --mixed:类似于–soft,只是不保留暂存区,只有工作区是原始版本的。

      $ git reset --mixed 7bb66f0fe9759bac901d12f7f2ac0aaafebd352a
      # 由于不保存暂存区,所以原来的文件都相当于新建的
      $ git status -s
      ?? b.txt
      ?? c.txt
      ?? d.txt
      ?? e.txt
      ?? s.txt
      ?? yut.txt
      

因此,在实际应用中,使用git checkout是最安全的,也是最方便的。因为git checkout在一个独立的分支上,如果想要回到之前的分支的最新版本只需要切换分支即可。而使用git reset还需要记住之前最新版本的版本号。

  • 19
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
回答: 公司使用Git基本流程包括以下几个步骤: 1. 初始化仓库:使用git init命令在项目文件夹中初始化一个Git仓库,生成.git隐藏文件夹,用于存储版本控制相关的信息。 2. 配置用户名和邮箱:使用git config --global user.name和git config --global user.email命令配置全局的用户名和邮箱地址,这些信息会被写入到.gitconfig文件中,以便在提交代码时标识作者身份。 3. 克隆远程仓库:使用git clone命令将远程仓库克隆到本地,可以通过指定远程仓库的URL或者名称来进行克隆。 4. 创建分支:使用git branch命令创建一个新的分支,可以基于主分支或其他已存在的分支进行创建。 5. 切换分支:使用git checkout命令切换到指定的分支,可以在不同的分支上进行开发和修改。 6. 添加和提交代码:使用git add命令将修改的文件添加到暂存区,然后使用git commit命令将暂存区的文件提交到本地仓库。 7. 拉取和推送代码:使用git pull命令从远程仓库拉取最新的代码到本地仓库,使用git push命令将本地仓库的代码推送到远程仓库。 8. 合并分支:使用git merge命令将一个分支的修改合并到另一个分支上,可以将开发完成的功能合并到主分支上。 9. 解决冲突:在合并分支或拉取代码时,如果存在冲突,需要手动解决冲突并提交修改。 10. 查看日志和版本:使用git log命令查看提交的日志记录,可以查看每次提交的作者、时间和修改内容等信息。 以上是公司Git使用的基本流程,可以根据具体的项目需求和团队协作方式进行调整和扩展。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* *3* [Git基本使用方法教程(入门级)](https://blog.csdn.net/weixin_71171795/article/details/127938111)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值