2.1 No Conflict
First, let’s see how git works on a normal revision, before we check how it behaves on
conflicts when merging. Let’s work with branches from example 09 (before we did
the merges). Right after checking out example9/branchA, we run git
status:
Listing 2.1:git status on clean working tree$ git status On branch example9/branchA nothing to commit, working tree clean
How does git know that there are no changes in my working tree? Git compares
the working tree with the index:
Listing 2.2:git ls-files on clean working tree$ git ls-files -s 100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0 .gitignore 100755 ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b 0 example.py 100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0 module.py
git is listing permissions for the files, object ID, index
stage
and the file name for each one of the files in the current revision. git compares the
files in the working tree and sees that they haven’t changed and so it reports no
changes.
Next thing, let’s modify bf example.py somehow. After modifying and saving, git
realizes that the file has changed because it does not match what is on index
anymore. Index information won’t change until we add the file, of course.
So let’s add the file in the index and check what git ls-files has for us
then:
Listing 2.3:git ls-files on a modified file$ git add example.py $ git status On branch example9/branchA Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: example.py $ git ls-files -s 100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0 .gitignore 100755 b30ade699b80860abd0ed6d84cff9df94e801d34 0 example.py 100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0 module.py
We can see that the id of the object for example.py has
changed
but other than that, there’s no other difference. How can git know what the ids of
those objects in index were before adding them? git is also checking the information
about HEAD:
Listing 2.4:git ls-tree on example9/branchA$ git ls-tree -r HEAD 100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f .gitignore 100755 blob ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b example.py 100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370 module.py
And we can see how the ids of the 3 files were the same as the ids that were in
the index when we checked out example9/branchA. Now that the id of
example.py has changed between HEAD and what’s on the index, git knows that
there’s a new content associated for example.py in index that is ready to be
committed. That’s why it’s showing up in Changes to be committed
now.
Let’s modify the file yet again without adding it and let’s see what happens:
Listing 2.5:After modifying staged file$ git status On branch example9/branchA Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: example.py Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: example.py $ git ls-tree -r HEAD 100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f .gitignore 100755 blob ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b example.py 100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370 module.py $ git ls-files -s 100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0 .gitignore 100755 b30ade699b80860abd0ed6d84cff9df94e801d34 0 example.py 100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0 module.py
This is interesting. example.py is showing up in Changes to be committed
because the id for the file has changed between HEAD and index. But it’s also
showing up in Changes not staged for commit because git notices that the
content of the file on the working tree is not matching the object on index. If we
added it now and we checked again:
Listing 2.6:After adding file again$ git add example.py $ git status On branch example9/branchA Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: example.py $ git ls-tree -r HEAD 100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f .gitignore 100755 blob ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b example.py 100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370 module.py $ git ls-files -s 100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0 .gitignore 100755 1858db13464ae33329a90cacbe294e749ea9a1a5 0 example.py 100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0 module.py
Notice how the id of the object associated to example.py in index has
changed now (from b30ade699b8.... to 1858db13464....). The ids of the
objects are still different between index and HEAD and that’s why the
file is showing up in Changes to be committed. The file content now
matches what is on index and that’s why git doesn’t need to say anything else
about the file. If we created a revision at this moment, what would be the
result?
Listing 2.7:committing$ git commit -m "Some test" [example9/branchA b2f9a40] Some test 1 file changed, 6 insertions(+) $ git status On branch example9/branchA nothing to commit, working tree clean $ git ls-tree -r HEAD 100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f .gitignore 100755 blob 1858db13464ae33329a90cacbe294e749ea9a1a5 example.py 100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370 module.py $ git ls-files -s 100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0 .gitignore 100755 1858db13464ae33329a90cacbe294e749ea9a1a5 0 example.py 100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0 module.py
Notice how the id of example.py has changed on
HEAD to
what was on index before we committed (1858db13464ae33329a90cacbe294e749ea9a1a5).
Now the ids of the files is the same between HEAD and index and the file in the
working tree matches what’s on index, so git says there’s nothing to report in git
status.
Let’s reset the branch before we play with conflicts:
Listing 2.8:Resetting$ git reset --hard HEAD~ HEAD is now at dfde76c A little refactor (moving condition to another function)