Проблемы с git, автоматически объединяющие конфликты содержимого файлов - PullRequest
0 голосов
/ 04 ноября 2018

Похоже, git не объединяет различия внутри файлов автоматически, даже если они возникают в непересекающихся областях. Находиться сразу за оригинальным репозиторием на ветке тоже не помогает.

Это приводит к следующей ситуации: A и B клонировали свои репозитории. A сделал некоторые изменения в файле F , зафиксировал и выдвинул их. B позже внес изменения и в F . Когда B попытается отправить свои изменения, он должен будет вручную просмотреть файл независимо от того, пересекаются ли изменения или они не .

Это действительно так? И все с этим живут?

Извините, но svn сделал это нормально, и я удивлен, что git, который считается превосходящим svn, не может делать некоторые базовые вещи, которые svn может. Для меня это шаг назад.

Кроме того, в случае конфликта git pull переведет файл B F в неработоспособное состояние с маркерами diff в теле. Любой рабочий процесс, связанный с изменениями прямо в рабочей области (что может быть хорошо - я объясню ниже), разрушается этим.


Допустим, у меня есть два клона некоторого репозитория - dev и prod - содержащие текстовый файл из двух строк.

> git init repo
Initialized empty Git repository in (...)
> cd repo
repo> printf "First line\nSecond line\n" > file.txt
repo> git add file.txt
repo> git commit -m "Added file.txt to the repo"
...
 1 file changed, 2 insertions(+)
 create mode 100644 file.txt
repo> git checkout --detach
HEAD is now at 32a4370 Added file.txt to the repo
repo> cd ..
> git clone repo dev
Cloning into 'dev'...
done.
> git clone repo prod
Cloning into 'prod'...
done.
> cd dev

В процессе разработки была изменена первая строка файла. Теперь содержимое файла должно выглядеть так:

First line v.2 
Second line

Теперь давайте зафиксируем изменения и отправим их в хранилище:

dev> git commit -a -m "Changed first line of file.txt"
...
 1 file changed, 1 insertion(+), 1 deletion(-)
dev> git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 274 bytes | 274.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /usr/home/1234ru/git-test/repo
   32a4370..15f1341  master -> master

Между тем какой-то коллега, который достаточно опытен, чтобы внести некоторые изменения в настоящий код (например, в случае веб-сайта это может быть редактирование шаблонов HTML, изменение некоторых настроек и т. Д. - все они существуют в форме физические файлы и должны находиться под контролем версий; может даже не потребоваться никаких навыков, если изменения сделаны через некоторый графический интерфейс для «обычных людей» (например, панели управления CMS сайта), но не достаточно опытных, чтобы что-то делать с git, редактирует файл file.txt в prod копии и изменяет его вторую строку, поэтому файл там выглядит так:

dev> cd ../prod
prod> cat file.txt
First line
Second line v.2

git знает, что была изменена только вторая строка файла:

> git diff
diff --git a/file.txt b/file.txt
index 7d91453..6a5dff7 100644
--- a/file.txt
+++ b/file.txt
@@ -1,2 +1,2 @@
 First line
-Second line
+Second line v.2

Также он понимает, что изменение находится сразу за основной веткой master и может быть быстро перенесено:

prod> git status
On branch master
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)
Changes not staged for commit:
   ...
        modified:   file.txt

svn удалось обновить рабочую копию из хранилища и объединить новые удаленные изменения с локальными изменениями. Посмотрим, как git сделает:

prod> git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /usr/home/1234ru/git-test/repo
   a8c50cb..005fa7c  master     -> origin/master
Updating a8c50cb..005fa7c
error: Your local changes to the following files would be overwritten by merge:
        file.txt
Please commit your changes or stash them before you merge.
Aborting

Так что не все так просто. Хорошо, давайте сначала попробуем зафиксировать это, а потом попробуем потянуть:

prod> git commit -a -m "Changed second line of file.txt"
...
 1 file changed, 1 insertion(+), 1 deletion(-)
prod> git pull
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
> cat file.txt
<<<<<<< HEAD
First line
Second line v.2
=======
First line v.2
Second line
>>>>>>> 005fa7c932456fb64bd81ebedf2a1fd821ddb0a0

Тоже не годится.

https://git -scm.com / book / ru / v2 / Git-Tools-Advanced-Merging говорит:

В отличие от некоторых других систем контроля версий, Git не пытается быть слишком умный в разрешении конфликтов слияния.

Так что не слишком умный, не совсем умный. В конце вместо двух команд - svn commit dev и svn update prod - теперь у меня должен быть набор ограничений и сценариев (которые я даже еще не понял).

Что вы, ребята, думаете обо всем, что сказал?


Для справки, вот как этот случай обрабатывается svn.

> svnadmin create repo
> svn checkout file://`pwd`/repo dev
Checked out revision 0.
> cd dev
dev> printf "First line\nSecond line\n" > file.txt
dev> svn add file.txt
A         file.txt
dev> svn commit -m "Added file.txt to the repo"
Adding         file.txt
Transmitting file data .done
Committing transaction...
Committed revision 1.
dev> cd ..
> svn checkout file://`pwd`/repo prod
A    prod/file.txt
Checked out revision 1

Теперь давайте изменим две разные строки в рабочих копиях dev и prod, зафиксируем изменения из dev и попробуем объединить их в prod с обновлением svn:

> cd dev
dev> vi file.txt

Содержимое файла должно выглядеть следующим образом (первая строка изменена):

First line v.2
Second line

dev> svn commit -m "Changed first line of file.txt"
Sending        file.txt
Transmitting file data .done
Committing transaction...
Committed revision 2.

Теперь вносим изменения в prod, НЕ обновляя рабочую копию заранее :

dev> cd ../prod
prod> vi file.txt

Содержимое файла должно выглядеть следующим образом (вторая строка изменена):

First line
Second line v.2

prod> svn diff
Index: file.txt
===================================================================
--- file.txt    (revision 1)
+++ file.txt    (working copy)
@@ -1,2 +1,2 @@
 First line
-Second line
+Second line v.2

Теперь обновляем продукт из репозитория:

prod> svn up
Updating '.':
G    file.txt
Updated to revision 2.

Флаг G означает «объединенный». Посмотрим, что внутри:

prod> cat file.txt
First line v.2
Second line v.2

Обе измененные строки здесь. Без ручной работы.

Фиксация также проходит гладко:

prod> svn commit -m "Changed second line of file.txt"
Sending        file.txt
Transmitting file data .done
Committing transaction...
Committed revision 3.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...