Let’s try it. Suppose Dracula takes a picture of Martian surface and
calls it mars.jpg
.
If you do not have an image file of Mars available, you can create
a dummy binary file like this:
$ head -c 1024 /dev/urandom mars.jpg
$ ls -lh mars.jpg
-rw-r--r-- 1 vlad 57095 1.0K Mar 8 20:24 mars.jpg
ls
shows us that this created a 1-kilobyte file. It is full of
random bytes read from the special file, /dev/urandom
.
Now, suppose Dracula adds mars.jpg
to his repository:
$ git add mars.jpg
$ git commit -m "Add picture of Martian surface"
[main 8e4115c] Add picture of Martian surface
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 mars.jpg
Suppose that Wolfman has added a similar picture in the meantime.
His is a picture of the Martian sky, but it is also called mars.jpg
.
When Dracula tries to push, he gets a familiar message:
To https://github.com/vlad/planets.git
! [rejected] main - main (fetch first)
error: failed to push some refs to 'https://github.com/vlad/planets.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
We’ve learned that we must pull first and resolve any conflicts:
$ git pull origin main
When there is a conflict on an image or other binary file, git prints
a message like this:
$ git pull origin main
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/vlad/planets.git
* branch main - FETCH_HEAD
6a67967..439dc8c main - origin/main
warning: Cannot merge binary files: mars.jpg (HEAD vs. 439dc8c08869c342438f6dc4a2b615b05b93c76e)
Auto-merging mars.jpg
CONFLICT (add/add): Merge conflict in mars.jpg
Automatic merge failed; fix conflicts and then commit the result.
The conflict message here is mostly the same as it was for mars.txt
, but
there is one key additional line:
warning: Cannot merge binary files: mars.jpg (HEAD vs. 439dc8c08869c342438f6dc4a2b615b05b93c76e)
Git cannot automatically insert conflict markers into an image as it does
for text files. So, instead of editing the image file, we must check out
the version we want to keep. Then we can add and commit this version.
On the key line above, Git has conveniently given us commit identifiers
for the two versions of mars.jpg
. Our version is HEAD
, and Wolfman’s
version is 439dc8c0...
. If we want to use our version, we can use
git checkout
:
$ git checkout HEAD mars.jpg
$ git add mars.jpg
$ git commit -m "Use image of surface instead of sky"
[main 21032c3] Use image of surface instead of sky
If instead we want to use Wolfman’s version, we can use git checkout
with
Wolfman’s commit identifier, 439dc8c0
:
$ git checkout 439dc8c0 mars.jpg
$ git add mars.jpg
$ git commit -m "Use image of sky instead of surface"
[main da21b34] Use image of sky instead of surface
We can also keep both images. The catch is that we cannot keep them
under the same name. But, we can check out each version in succession
and rename it, then add the renamed versions. First, check out each
image and rename it:
$ git checkout HEAD mars.jpg
$ git mv mars.jpg mars-surface.jpg
$ git checkout 439dc8c0 mars.jpg
$ mv mars.jpg mars-sky.jpg
Then, remove the old mars.jpg
and add the two new files:
$ git rm mars.jpg
$ git add mars-surface.jpg
$ git add mars-sky.jpg
$ git commit -m "Use two images: surface and sky"
[main 94ae08c] Use two images: surface and sky
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 mars-sky.jpg
rename mars.jpg = mars-surface.jpg (100%)
Now both images of Mars are checked into the repository, and mars.jpg
no longer exists.