The workings and concepts of Git - Reader's Digest

concepts

The repository holds all versions of the content, while the working directory is the place where you modify the code. You checkout code from the repository to the working directory and commit changes you’ve made in this working directory back into a new version of the content in the repository.

The main principle of Git

First, Git handles content in snapshots, one for each commit, and knows how to apply or roll back the change sets between two snapshots. This is an important concept. In my opinion, understanding the concept of applying and rolling back change sets makes Git much easier to understand and work with. This is the real basic principle. Anything else follows from this.

Naming

Snapshots are the main elements in Git. They are named with the commit ID, which is a hash ID like “c69e0cc32f3c1c8f2730cade36a8f75dc8e3d480” for example.

Note that the term commit, is used both as verb for creating a snapshot and as name for the resulting snapshot.

Normally you don’t have to work with the commit IDs; instead you work with branches.

In Git, a stream of changes is an ordered list of change sets as they are applied one after another to go from one snapshot to the next. A branch in Git is only a named pointer to a specific snapshot. It notes the place where new changes should be applied to when this branch is used. When a change is applied to a branch, then also the branch label moves to the new commit.

How does Git know where to put the change from a workspace? That is where HEAD points. The HEAD of the development is where you last checked out your workspace and, more importantly, where to commit the changes. It usually points to the branch you last checked out.

The tag command names a commit and allows you to address the individual commit with a readable name. Basically, a tag is an alias for a commit ID but commits can also be addressed with some shortcuts.

gitrevisions is a revision parameter typically, but not necessarily, names a commit object.

Because names like tags or branch names are references to commits, they are called refnames. A reflog shows what has been changed during the lifetime of the name, from when it was created (usually by a branch) until the current state.

Branching

The concept behind branching is that each snapshot can have more than one child. Applying a second change set to the same snapshot creates a new, separate stream of development. And if it is named, it is called a branch.

Branches are created with the git branch <branch name> command on the current HEAD, or git branch <branch name> <commit id> on any valid snapshot version. This creates a new branch pointer in the repository. Be careful, branching this way leaves your workspace at the old branch. You need to checkout the new branch first. With git checkout -b <branch name> the new branch is created, and your workspace is also moved to the new branch.

Two other commands are rather useful:

  • git diff <branch> -- <path> as already mentioned above prints a diff of the given path (file or directory) between the current working directory and the specified branch.
  • git checkout <branch> -- <path> checks out files from a different branch into the working directory, so you can pick changes from another branch.

useful commands concerning to branch

  • git branch — creates a new branch from the current HEAD (working directory).
  • git checkout -b — creates a new branch from the current HEAD, and switches the working directory to the new branch.
  • git diff – — shows the difference of between the working directory and the given branch.
  • git checkout – — checks out files from the given branch into the working directory.
  • git merge — merges the given branch into the current branch.
  • git merge -abort — aborts a merge that resulted in conflicts.

Merging

When you implemented your new feature, you checked it into the repository, for example, on your “feature” branch. When the feature is finished, you need to merge it back into the master branch. You do this by checking out the master branch, and use git merge <branch name>. Git then merges the changes from the given branch into the checked out branch. What Git does to achieve this is it applies all of the change sets from the feature branch onto the tip of the master branch.

Depending on the type of changes in the two branches, and possible conflicts, there are three possibilities that can happen.

  • Fast forward merge
  • No-conflict merge
  • Conflicting merge

merge conflict

如何消除对合并时出现冲突的恐惧心理?

  • 首先可以放心的是,你随时可以撤销一个合并操作,并且返回到冲突发生之前的状态。
  • 只要在命令行界面中键入 git merge --abort 命令,你的合并操作就会被安全的撤销。
  • 当你解决完冲突,并且在合并完成后发现一个错误,仍然还有机会来简单地撤销它。你只须键入 git reset --hard 命令,系统就会回滚到那个合并开始前的状态

git status 显示 unmerged paths,表明存在冲突

发生冲突的文件的内容

  • Git 会非常友好地把文件中那些有问题的区域在 <<<<<<< HEAD>>>>>>> other/branch/name 之间标记出来。

  • 第一个标记后的内容源于当前分支。在尖括号之后,Git 会告诉我们这些改动是从哪里(哪个分支)来的。然后有冲突的改动会被 ======= 分割起来。

  • 使用一个专门的合并工具可以使清理这些冲突变得更容易,你可以通过 git config 命令来设置这个合并工具给 Git。之后当发生合并冲突时,你可以使用 git mergetool 命令来调用这个工具。

  • 手动处理冲突,你必须手动地将文件标记为已解决状态(通过执行命令 git add <filename>)。最终,当所有的冲突被解决后,你必须通过一个正常的提交操作来完成这个清理合并冲突的工作。

resources