У меня есть две ветви 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 попытаться объединить любые файлы, которые различаются между двумя ветвями?
Все как ожидалось.
#!/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
Если есть конфликты, они появятся автоматически, просто исправьте их, если они у вас есть.
Я думаю, что моя проблема нечетко объяснена в ОП, поэтому я отредактирую, чтобы добавить конкретный воспроизводимый пример.
Я потратил много времени на написание для вас примера на основе вашего вопроса :-(
Я поэкспериментировал с этим еще немного и пришел к выводу, что ваш ответ на самом деле правильно отвечает на мой вопрос, но я не понял, так что спасибо.
Меня не волнует история коммитов B, и на самом деле она мне даже не нужна. Мне просто нужен коммит с надписью «перенести изменения из B».
Тогда вы можете объединить B с A с помощью нашей стратегии слияния*. Эта стратегия фактически не вносит никаких изменений из другой ветки (B) в целевую ветку (A). Он просто помечает изменения как объединенные и сохраняет только версию целевой ветки.
Это не следует путать с нашей стратегией слияния, которая вообще не учитывает, что содержит другое дерево. Оно отбрасывает все, что сделало другое дерево, заявляя, что наша история содержит все, что с ней произошло.
git merge -s ours B
* При чтении документации не запутайтесь в первом абзаце (тот, который я не прикрепил), этот раздел относится к опции -X, которая представляет собой логику, к которой Git возвращается только в случае конфликтов. Вместо этого второй абзац относится к опции -s, которая сохраняет только версию целевой ветки и игнорирует другую ветку независимо от того, есть ли конфликты или нет.
Итак, какую команду мне запустить, чтобы она автоматически попыталась объединить все разные файлы? Нужно ли мне вручную
git checkout A — file
вручную проверять каждый из них и просматривать различия каждого из них, чтобы вручную разрешать конфликты?