Синхронизация расходящихся ветвей друг с другом

У меня есть две ветви A и B, которые разошлись.

Я хочу периодически синхронизировать их друг с другом (фиксировать большинство изменений из B в A и фиксировать большинство изменений из A в B).

При слиянии в любом направлении это может привести к отклонению целых файлов или только частей файла.

Первое, что я сделал, это:

git checkout A
git merge --squash B

Меня не волнует история коммитов B, и на самом деле она мне даже не нужна.
Мне просто нужен коммит с надписью «перенести изменения из B».

Я разрешил все изменения и зафиксировал их в A. Затем сделал обратное:

git checkout B
git merge --squash A

На данный момент git распознает изменение только пары файлов. В частности, если я запущу git diff --name-only A, я получу огромный список различий, порядка 100 разных файлов.

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

Как мне заставить git попытаться объединить любые файлы, которые различаются между двумя ветвями?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Все как ожидалось.

  • Вот демо, показывающее, как это работает (как вы уже знаете :-))
  • В конце скрипта вы увидите, как «git» сжимает коммиты и «исправляет» разные файлы, как вы их описали.
#!/bin/bash

###
### Merge conflict demo
###

# Create a new demo repository
rm -rf   /tmp/tempRepository
echo -e ""
echo -e "* Preparation(s)"
echo -e ""

mkdir -p /tmp/tempRepository
git init /tmp/tempRepository
cd       /tmp/tempRepository

echo -e "------------------------------------------------------------------------"
echo -e "$ git checkout -b branchA"
echo -e ""

# Create a new branch
git checkout -b branchA

# Add some content to it
echo -e "------------------------------------------------------------------------"
echo -e "* Initial commit to branchA"
echo -e ""
echo  "Hello World" > hello.txt
git   add hello.txt
git   commit -m "Initial commit"

# Create a new branch from branchA
echo -e "-------------------------------------------------------------------------"
echo -e "* Create branch B branchA (and dont switch to branchB)"
echo -e ""
echo -e "$ git checkout -b branchB"
echo -e ""
echo -e "git branch branchB"
git branch branchB

# Add some content to it (and generate conflict)
echo -e "-------------------------------------------------------------------------"
echo -e "* Create change in branchA (after branchB was created from A)"
echo -e ""
echo  "Hello World2" > hello.txt
git   add hello.txt
git   commit -m "Commit on branchA"

# Add some ramdom commits to branchA
echo -e "-------------------------------------------------------------------------"
echo -e "* Add random content to branchA"
echo -e ""
for i in {1..5};
do
    echo  "$RANDOM" > A-$RANDOM.txt
    git   add .
    git   commit -m "Commit [$i] on branchA"
done

# Add some ramdom commits to branchB
echo -e "-------------------------------------------------------------------------"
echo -e "* Checkout & Add random content to branchB"
echo -e ""

git checkout branchB
for i in {1..5};
do
    echo  "$RANDOM" > B-$RANDOM.txt
    git   add .
    git   commit -m "Commit [$i] on branchB"
done

# Checkout branchA
echo -e "-------------------------------------------------------------------------"
echo -e "$ git checkout branchA"
echo -e ""
git checkout branchA

# Merge branchB into branchA with squash
echo -e "-------------------------------------------------------------------------"
echo -e "$ git merge --squash branchB"
echo -e ""
git merge --squash branchB

# See the diffrence
echo -e "-------------------------------------------------------------------------"
echo -e "$ git diff --name-only branchA"
echo -e ""
git diff --name-only branchA

# Wait for user input
echo "Press any key to continue..."
read -n 1

# Check the staging area
echo -e "-------------------------------------------------------------------------"
echo -e ""
echo -e "$ git status"
echo -e ""
git status

# Commit the changes
echo -e "-------------------------------------------------------------------------"
echo -e ""
echo -e "* Commit the changes (results of the squashing)"
echo -e ""
echo -e "$ git commit -m"Cool commit""
echo -e ""
git commit -m"Cool commit"

# View the list of chanegs files
echo -e "-------------------------------------------------------------------------"
echo -e ""
echo -e "* Verify that all is "fixed""
echo -e ""
echo -e "$ git whatchanged --oneline  | cat"
echo -e ""
git whatchanged --oneline  | cat

Выход


* Preparation(s)

Initialized empty Git repository in /private/tmp/tempRepository/.git/
------------------------------------------------------------------------
$ git checkout -b branchA

------------------------------------------------------------------------
* Initial commit to branchA

[branchA (root-commit) 5582b4e] Initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 hello.txt
-------------------------------------------------------------------------
* Create branch B branchA (and dont switch to branchB)

$ git checkout -b branchB

git branch branchB
-------------------------------------------------------------------------
* Create change in branchA (after branchB was created from A)

[branchA ad5738d] Commit on branchA
 1 file changed, 1 insertion(+), 1 deletion(-)
-------------------------------------------------------------------------
* Add random content to branchA

[branchA d20f973] Commit [1] on branchA
 1 file changed, 1 insertion(+)
 create mode 100644 A-8451.txt
[branchA 3690e93] Commit [2] on branchA
 1 file changed, 1 insertion(+)
 create mode 100644 A-18701.txt
[branchA c90a2fa] Commit [3] on branchA
 1 file changed, 1 insertion(+)
 create mode 100644 A-19933.txt
[branchA ab06b25] Commit [4] on branchA
 1 file changed, 1 insertion(+)
 create mode 100644 A-8861.txt
[branchA 2261f61] Commit [5] on branchA
 1 file changed, 1 insertion(+)
 create mode 100644 A-25228.txt
-------------------------------------------------------------------------
* Checkout & Add random content to branchB

[branchB ff49491] Commit [1] on branchB
 1 file changed, 1 insertion(+)
 create mode 100644 B-30774.txt
[branchB 4e96ed8] Commit [2] on branchB
 1 file changed, 1 insertion(+)
 create mode 100644 B-30658.txt
[branchB 299fd31] Commit [3] on branchB
 1 file changed, 1 insertion(+)
 create mode 100644 B-28765.txt
[branchB 2bc2c61] Commit [4] on branchB
 1 file changed, 1 insertion(+)
 create mode 100644 B-4777.txt
[branchB 7321b52] Commit [5] on branchB
 1 file changed, 1 insertion(+)
 create mode 100644 B-6593.txt
-------------------------------------------------------------------------
$ git checkout branchA

-------------------------------------------------------------------------
$ git merge --squash branchB

Squash commit -- not updating HEAD
-------------------------------------------------------------------------
$ git diff --name-only branchA

B-28765.txt
B-30658.txt
B-30774.txt
B-4777.txt
B-6593.txt
Press any key to continue...
-------------------------------------------------------------------------

$ git status

On branch branchA
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    new file:   B-28765.txt
    new file:   B-30658.txt
    new file:   B-30774.txt
    new file:   B-4777.txt
    new file:   B-6593.txt

-------------------------------------------------------------------------

* Commit the changes (results of the squashing)

$ git commit -mCool commit

[branchA 216cca4] Cool commit
 5 files changed, 5 insertions(+)
 create mode 100644 B-28765.txt
 create mode 100644 B-30658.txt
 create mode 100644 B-30774.txt
 create mode 100644 B-4777.txt
 create mode 100644 B-6593.txt
-------------------------------------------------------------------------

* Verify that all is fixed

$ git whatchanged --oneline  | cat

216cca4 Cool commit
:000000 100644 0000000 62eb110 A    B-28765.txt
:000000 100644 0000000 c6d2238 A    B-30658.txt
:000000 100644 0000000 0694fb8 A    B-30774.txt
:000000 100644 0000000 87768b1 A    B-4777.txt
:000000 100644 0000000 179d206 A    B-6593.txt
2261f61 Commit [5] on branchA
:000000 100644 0000000 76fdbb7 A    A-25228.txt
ab06b25 Commit [4] on branchA
:000000 100644 0000000 d5edada A    A-8861.txt
c90a2fa Commit [3] on branchA
:000000 100644 0000000 d69a04c A    A-19933.txt
3690e93 Commit [2] on branchA
:000000 100644 0000000 e9880db A    A-18701.txt
d20f973 Commit [1] on branchA
:000000 100644 0000000 79e927c A    A-8451.txt
ad5738d Commit on branchA
:100644 100644 557db03 b2b6f00 M    hello.txt
5582b4e Initial commit
:000000 100644 0000000 557db03 A    hello.txt

Итак, какую команду мне запустить, чтобы она автоматически попыталась объединить все разные файлы? Нужно ли мне вручную git checkout A — file вручную проверять каждый из них и просматривать различия каждого из них, чтобы вручную разрешать конфликты?

Zachary Turner 26.04.2024 01:43

Если есть конфликты, они появятся автоматически, просто исправьте их, если они у вас есть.

CodeWizard 26.04.2024 01:48

Я думаю, что моя проблема нечетко объяснена в ОП, поэтому я отредактирую, чтобы добавить конкретный воспроизводимый пример.

Zachary Turner 26.04.2024 01:52

Я потратил много времени на написание для вас примера на основе вашего вопроса :-(

CodeWizard 26.04.2024 01:54

Я поэкспериментировал с этим еще немного и пришел к выводу, что ваш ответ на самом деле правильно отвечает на мой вопрос, но я не понял, так что спасибо.

Zachary Turner 30.04.2024 18:15

Меня не волнует история коммитов B, и на самом деле она мне даже не нужна. Мне просто нужен коммит с надписью «перенести изменения из B».

Тогда вы можете объединить B с A с помощью нашей стратегии слияния*. Эта стратегия фактически не вносит никаких изменений из другой ветки (B) в целевую ветку (A). Он просто помечает изменения как объединенные и сохраняет только версию целевой ветки.

Это не следует путать с нашей стратегией слияния, которая вообще не учитывает, что содержит другое дерево. Оно отбрасывает все, что сделало другое дерево, заявляя, что наша история содержит все, что с ней произошло.

git merge -s ours B

* При чтении документации не запутайтесь в первом абзаце (тот, который я не прикрепил), этот раздел относится к опции -X, которая представляет собой логику, к которой Git возвращается только в случае конфликтов. Вместо этого второй абзац относится к опции -s, которая сохраняет только версию целевой ветки и игнорирует другую ветку независимо от того, есть ли конфликты или нет.

Другие вопросы по теме