Похоже, 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.