Страницы

Поиск по вопросам

Показаны сообщения с ярлыком git-merge. Показать все сообщения
Показаны сообщения с ярлыком git-merge. Показать все сообщения

вторник, 7 апреля 2020 г.

Не дает сделать merge

#git #git_merge

                    
Сделал новую ветку и сделал merge, после чего добавил исправленный после конфликта
файл и пишу git commit и тут такое:

 

Merge branch 'branch'

# Conflicts:
#       myfile.txt
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#       .git/MERGE_HEAD
# and try again.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be commited:
#   modified:   myfile.txt
#


что делать?
    


Ответы

Ответ 1



как я понял, при попытке слияния у вас возник конфликт. вы его устранили и командой commit повторяете попытку слияния. при этом запустился редактор vim для редактирования сообщение о слиянии. сразу предложен и обычно вполне подходящий вариант — в первой строке. после сохранения файла (:wq, затем enter) пустые и закомментированные строки будут отброшены. в них — всего лишь подсказки для вас. дополнение если вы всё-таки хотите отказаться от этого коммита, удалите все непустые и незакомментированные строки (в приведённом случае — одна первая строка), для чего переместите «курсор» (например, с помощью стрелок вверх/вниз) на удаляемую строку и нажмите dd. а потом сохраните файл, как написано выше. commit не будет создан.

пятница, 13 марта 2020 г.

git pull accept theirs/ours

#git #git_merge #git_pull


Можно ли как-то заставить git во время pull-а использовать стратегию слияния theirs
для конкретной директории? Но если конфликты возникнут в других местах - пусть предоставить
мне возможность решать.

Сейчас в голову приходит только такое:
делаем hook, который отрабатывает после pull-а, и запускает git checkout --theirs
{моя директория}
    


Ответы

Ответ 1



на основе ответа: Simple tool to 'accept theirs' or 'accept mine' on a whole file using git для частичной автоматизации можно, например, использовать псевдонимы: $ git config --global alias.accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f" $ git config --global alias.accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f" и при возникновении конфликта после git pull для файлов/каталогов, которые должны быть ours, выполнить: $ git accept-ours -- файлы/каталоги ... а для тех, что должны быть theirs: $ git accept-theirs -- файлы/каталоги ...

четверг, 23 января 2020 г.

Git. Удалить родителя из коммита или отменить слияние

#git #github #git_merge #git_rebase


Здравствуйте. Имеется следующая ветка:

* c9ec96c Some Changes in EG proj
*   928b5ea Merge branch 'testHDFS'
|\
| * 1504e3f Redact Task
| * a9dffca Add xmlResult
| * 82cd8fb EGp with MetaCode
| * db93620 Add EG progect to test
* | 536029f Redact Task
* | 44cc081 Add xmlResult
* | 370584a EGp with MetaCode
* | 96c5388 Add EG progect to test
|/
* 765ca4c v5HDFS
* 5da3f2a v4HDFS
* cedc686 v3HDFS
* 28d0e1a v2HDFS
* a6f9d63 v1HDFS
* e5f373a v3
* 708e3b6 v2
* c89f76a First commit


Ответвление от 765ca4c появилось после попытки переписать e-mail автора коммитов.
Затем последовало слияние двух одинаковых коммитов (возможно вовремя не слил все изменения
с github). Необходимо удалить дублирующую ветку.

Были следующие попытки исправить ситуацию:


git rebase --onto c9ec96c 536029f как посоветовали здесь. Результат:


  First, rewinding head to replay your work on top of it...
  
  Fast-forwarded HEAD to c9ec96c.

git reset --hard 1504e3f дабы удалить коммит вовсе (принимая во внимание, что это
может привести к плачевным последствиям)


UPD:
Попробовал метод от @alexander barakin, вот что получилось:


git checkout c9ec96с
git rebase -i 765ca4c

pick 96c5388 Add EG progect to test
pick 370584a EGp with MetaCode
pick 44cc081 Add xmlResult
pick 536029f Redact Task
pick db93620 Add EG progect to test
pick 82cd8fb EGp with MetaCode
pick a9dffca Add xmlResult
pick 1504e3f Redact Task
pick c9ec96c Some Changes in EG proj


Затем:

pick 96c5388 Add EG progect to test
pick 370584a EGp with MetaCode
pick 44cc081 Add xmlResult
pick 536029f Redact Task
pick c9ec96c Some Changes in EG proj
:x



  Successfully rebased and updated detached HEAD.

git log --oneline --graph

* f647a1b Some Changes in EG proj
* 536029f Redact Task
* 44cc081 Add xmlResult
* 370584a EGp with MetaCode
* 96c5388 Add EG progect to test
* 765ca4c v5HDFS
* 5da3f2a v4HDFS
* cedc686 v3HDFS
* 28d0e1a v2HDFS
* a6f9d63 v1HDFS
* e5f373a v3
* 708e3b6 v2
* c89f76a First commit

git checkout master

Warning: you are leaving 1 commit behind, not connected to any of your branches:
        f647a1b Some Changes in EG proj
If you want to keep it by creating a new branch, this may be a good time to do so with:
        git branch  f647a1b
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

git log --oneline --graph

* c9ec96c Some Changes in EG proj
* 928b5ea Merge branch 'testHDFS'
|\
| * 1504e3f Redact Task
| * a9dffca Add xmlResult
| * 82cd8fb EGp with MetaCode
| * db93620 Add EG progect to test
* | 536029f Redact Task
* | 44cc081 Add xmlResult
* | 370584a EGp with MetaCode
* | 96c5388 Add EG progect to test
|/
* 765ca4c v5HDFS
* 5da3f2a v4HDFS
* cedc686 v3HDFS
* 28d0e1a v2HDFS
* a6f9d63 v1HDFS



Я понимаю, что создалась новая ветка и я могу по хэшу переключиться на head. Но не
понимаю почему не удалились старые коммиты. Пытался дропнуть их и через rebase и через
reset. Если ввести команду rebase для f647a1b (пересчитанный коммит), то на него смотрят
коммиты, которые  "выше" c9ec96c. Видимо не до конца произошло перебазирование и появился
конфликт.
    


Ответы

Ответ 1



насколько я понял, вы хотите удалить четыре «продублированных» коммита (и коммит слияния). для этого можно воспользоваться интерактивным вариантом команды rebase: $ git rebase -i коммит.до.разветвления пример: $ git log --oneline --graph * aabf478 7 * 5430d97 6 * 696565e bind |\ | * dff29c3 15 | * 5709144 14 | * 133cf40 13 * | 1807d0e 5 * | f61ce99 4 * | c5c42a9 3 |/ * c521dd2 2 * fd32efc 1 требуется, чтобы история выглядела так: 1 - 2 - 3 - 4 - 5 - 6 - 7, а коммиты с сообщениями 13, 14, 15 и bind — вообще убрать. в данном случае коммит до разветвления — это коммит с сообщением 2 и хэшем c521dd2: $ git rebase -i c521dd2 откроется редактор со следующими строками (обратите внимания — коммита слияния с сообщением bind в этом списке нет (и не должно быть)): pick c5c42a9 3 pick f61ce99 4 pick 1807d0e 5 pick 133cf40 13 pick 5709144 14 pick dff29c3 15 pick 5430d97 6 pick aabf478 7 надо просто удалить строки с сообщениями 13, 14, 15, чтобы остался такой список: pick c5c42a9 3 pick f61ce99 4 pick 1807d0e 5 pick 5430d97 6 pick aabf478 7 сохраняем файл и закрываем редактор. git закончит работу и выдаст примерно следующее: Successfully rebased and updated refs/heads/master. теперь история выглядит так, как требовалось: $ git log --oneline --graph * 894f56f 7 * 305ff84 6 * 1807d0e 5 * f61ce99 4 * c5c42a9 3 * c521dd2 2 * fd32efc 1 естественно, хэши у перезаписанных коммитов (с сообщениями 6 и 7) изменились. но «содержание» у них осталось прежним, и в рабочем каталоге сейчас та же «картина», что и до вызова rebase.

пятница, 10 января 2020 г.

Слияние в GIT и командная работа

#git #git_branch #git_merge


Помогите, пожалуйста, разобраться с командной работой в Git.
Пока работа настроена так:
2 программиста: 1 делает работу, другой проверяет.

Тот который делает получает таски, для выполнения каждого таска создает новую ветку
после после того как выполнил задание пушит эту ветку на сервер, сливает ветку со своим
мастером делает новую ветку для таска и т.д.

Проверяющий забирает ветки с сервера и делает проверку если все ок вливает их в мастер
отправляет на сервер. Если сделаны ошибки возобновляет таск.

Это все как-то коряво, я думаю можно сделать лучше, подскажите как, наведите на правильный
путь!

Сейчас проблемы возникают на этапе проверки при слиянии веток. Как можно слить только
те комиты которые были сделаны в сливаемой ветке ? 
    


Ответы

Ответ 1



Как можно слить только те комиты которые были сделаны в сливаемой ветке ? В git под термином «ветка» (branch) подразумевается указатель на коммит, а не набор коммитов, как в некоторых других системах управления версиями файлов. Иными словами, это точка, а не отрезок. Вам требуется перенести несколько коммитов (отрезок), а для этого нужно указать две точки. К примеру: одобренная задача решалась в ветке task125, а предыдущая, пока не одобренная задача, решалась в ветке task124. Тогда для включения (в текущую ветку) одобренных коммитов (отрезка между этими двумя точками) можно использовать такую, например, команду: git cherry-pick task124..task125

четверг, 2 января 2020 г.

Как работает git merge --squash?

#git #git_merge


Заметил что иногда вместо git pull --rebase делаю так

git checkout remote_my/branch_my
git merge --squash branch_my
git commit ...


В чем смысл такого кода
    


Ответы

Ответ 1



Из Git Reference - merge: --squash Обрабатывает рабочую область и индекс таким образом, как будто было произведено слияние (merge), но при этом не делает фактического коммита, не перемещает указатель HEAD и не записывает ничего в $GIT_DIR/MERGE_HEAD. Это позволяет сделать единый коммит к текущей ветке, содержащий все те же изменения, которые были бы применены при обычном слиянии с веткой (или несколькими, в случае сложного слияния). Как это работает git checkout master git merge --squash feature123 git commit -m'merged feature #123' Все изменения в ветке feature123 становятся одним коммитом в ветке master. Это удобно, если ветка содержит много незначительных коммитов, которые «неинтересны» для общей истории. После такой операции история ветки останется «плоской», так же как после git pull --rebase.

четверг, 26 декабря 2019 г.

Важно ли использование --no-ff при слиянии веток?

#git #git_merge


При слиянии веток в git можно указать флаг --no-ff, который отключит fast-forward.
Какие есть +/- --no-ff кроме возможности увидеть красивый график наследования веток?
Где вы используете --no-ff?
    


Ответы

Ответ 1



--no-ff удобен для реверта. Если много людей делают код и много коммитят в свои ветки (а в случае гита - это абсолютно нормально), то с включенным fast-forward история превратится в нечитаемое мессиво. И если потом нужно будет какой-то объем работ откатить, то это может быть сложно. Да, я знаю о том, что коммиты можно перегруппировать перед мерджем. Но некоторых нужно ещё научить этому. В одном с моих проектов этот флаг установлен глобально по желанию менеджмента.

среда, 25 декабря 2019 г.

Слияние веток, в одной из которых файлы были не переименованы, а удалены и созданы в другом каталоге

#git #git_merge




В последнем коммите ветки hometype есть изменения, которые должны быть в ветке master,
но влить ее в мастер не получается, потому что в коммите Rename были изменены названия
пакетов, что в общем означает новое местоположение файла/класса.

Получается, что в ветке master файлы, для которых есть изменения в hometype, находятся
в других местах.

Как их теперь объединить, если это вообще возможно?
    


Ответы

Ответ 1



судя по всему, git «не знает» о произведённых (в ветке master) переименованиях, и не может «связать» изменения, произведённые в другой (hometype) ветке (со «старыми» файлами), с файлами «новыми». один из возможных (но не самый «изящный» из) путей «влить» изменения из другой ветки (hometype) в основную — получить патч из изменений, внесённых в ветке hometype, вручную исправить в нём имена файлов, и «наложить» патч в основной ветке командой git apply файл.с.патчем (см. man git-apply). совет: тренироваться лучше на тестовой ветке, создав её командой git checkout -b тестовая-ветка исходная-ветка. изменять надо будет такие примерно строки: diff --git a/file1 b/file1 index 88621c5..af3bc11 100644 --- a/file1 +++ b/file1 здесь имя файла, которое надо будет вручную исправить — file1, оно встречается четыре раза, и все четыре его появления надо исправить. будьте внимательны: так как у вас были исправления, судя по всему, нескольких файлов, то блоков таких будет больше одного. получить патч из изменений, внесённых commit-ом, зная его хэш, можно, например, так: $ git diff хэш^ хэш запись хэш^ означает в данном случае «родительский» (parent) commit для данного commit-а. см. man git-diff на предмет подробностей об этой команде и man gitrevisions о смысле ^ и подобных модификаторов. в будущем я бы порекомендовал переименования файлов/каталогов делать отдельным коммитом (отдельным от изменения содержимого этих же файлов). тогда программа git без дополнительных указаний должна распознавать такие переименования. другой путь решения озвученной в вопросе проблемы (он более «изящен», но требует довольно длинного описания) как раз и основывается на указании программе git, какую долю изменений в файле, «удалённом в одном месте и созданном в другом», следует считать переименованием. для команды merge это делается с помощью опции rename-threshold стратегии recursive. см. описание этой опции в man git-merge и опции -M в man git-diff.

воскресенье, 1 декабря 2019 г.

Как разрешается конфликт изменений при слиянии ветвей?

#git #git_merge


Диспозиция такая:

Есть две ветки. в каждой из них присутствует файл который редактировался (один и тот же).

При слиянии веток что произойдет с этим файлом?
    


Ответы

Ответ 1



Если кратко: произойдет конфликт слияния (merge conflict) и его нужно будет как-то разрешить. Для бинарных файлов: только выбрать версию А или Б (или другие, если octomerge). Бывает, что бинарные файлы Git воспринимает как текстовые и тогда merge их необратимо портит. Это прежде всего относится к файлам office-форматов. Для текстовых файлов: пара вариантов: Вручную разрешить конфликты После merge в файле появятся куски из обеих сливаемых версий, как-то так: <<<<<<< HEAD содержимое файла из первой ветки ====== содержимое файла из второй ветки >>>>>>> otherbranch Нужно будет вручную отредактировать конфликтный файл (или файлы), при этом не забывая удалить метки, оставленные Git (>>>>>>> otherbranch). Затем: git add conflicting-file-name.txt git commit -m'merged A and B' Выбрать одну из версий файла Можно явным образом указать: какой файл выбирать. Подходит, только если одна из версий не нужна. git checkout --ours a.txt git checkout --theirs a.txt git add a.txt git commit -m "added theirs" Сделал вам тестовый репозиторий, чтобы сразу клонировать и посмотреть, как оно работает. git clone https://github.com/NickVolynkin/git-merge-test.git cd git-merge-test git merge otherbranch open a.txt В файле видны отметки, можете с ним теперь проделать вышеописанные действия. Подробнее написано в книге Pro Git на русском. Ее обязательно нужно прочитать, прежде чем работать со слиянием веток. Фундаментальное понимание процесса ничем не заменить. Потренироваться с ветвлением и слиянием можно тут: Learn Git Branching.

Ответ 2



проблемы с мерджем могут возникнуть из-за использования неудобного редактора. Попробуйте сменить Ваш консольный редактор на IDE или специализированный софт для этих нужд https://git-scm.com/download/gui/linux Nick Volynkin теорию скинул

среда, 27 ноября 2019 г.

Зачем нужен pull request, если есть push?


На текущем проекте мне советовали загружать каждый таск так: 


Создаем ветку по имени таска
Комитим
pull request - Отправляем все на удаленный репозиторий
Далее мне советуют: "смотришь код и мерджишь"


Не совсем понятен четвертый пункт.
Мне советуют для каждого таска ветвь создавать, заливать в нее изменения, и сливать обратно с master.
Я понимаю, что репозитория два: локальный и удаленный.


Т.е. мне создавать на локальном ветку, коммитить, мержить и пушить на удаленный репозиторий? Перед этим всем скачать обновления с удаленного.
Зачем тогда нужен pull request, если push и так отправляет данные в удаленный репозиторий?

    


Ответы

Ответ 1



Организация работы, основанная на пулл-реквестах (pull-request, merge-request, запро на слияние), характерна для распредленных проектов, которые размещаются на специальны хостингах репозиториев. Git сам по себе не имеет такого функционала, он реализуется именно хостингом. Кроме GitHub эту возможность предоставляет Gitlab, возможно есть и другие хостинги. Называется такая организация GitHub flow или Gitlab flow - в противоположность более традиционному Git flow git-flow ("flow" - поток). Про организацию Git flow можно почитать в описании метки. Кратко: есть основная ветк master, разработчики создают ветки под конкретные задачи (фича, багфикс), потом сливают их в master. Возможно использование ветки-агрегатора develop, в которой копятся изменения до момента очередного релиза. Git flow реализуем, когда у всех разработчиков есть право создавать новые ветки удалённом репозитории. Это часто так при закрытой разработке внутри компании, но почти всегда не так, когда проект хостится открыто. Нельзя просто так взять и запушить свою ветку в чужой репозиторий на GitHub. Другое важное право - сливать изменения в ветку master или другую, из которой ко уходит в производство. В открытом репозитории это может делать владелец или группа уполномоченны пользователей. В закрытом код обычно может сливать ответственный за это сотрудник. Перед слиянием код может и должен проходить инспекцию и тестироваться. Если у вас не так - повод обеспокоиться. Чтобы у разработчиков всё-таки была возможность принимать участие, коммитить сво изменения/дополнения и потом предлагать слить их в основную ветку проекта, были придуман форки (fork, вилка). Форк - это ваша собственная копия целого репозитория Git. В ней вы можете создавать собственные ветки, делать новые коммиты и всё остальное, что можно делать с принадлежащим вам репозиторием. Чтобы предложить добавить ваши изменения в основной репозиторий, используется пулл-реквест. Алгоритм создания такой: Создаете локальную ветку. Создаете в ней новые коммиты (иначе нет смысла в слиянии). Пушите эту локальную ветку на удаленный репозиторий. Заходите на сайт хостинга репозиториев. Там выбираете одну из веток вашего удаленног репозитория и предлагаете влить её в одну из веток другого удалённого репозитория. Как вариант, если у вас есть право создавать ветки, но нет права сливать в master - можно создавать пулл-реквест внутри одного репозитория. Нажимаете кнопку подтверждения. Теперь создаётся собственно пулл-реквест, как сущность. У него в том числе есть: Номер и url. Он также появляется в списке открытых реквестов целевого репозитория. Информация о внесённых изменениях в формате diff. Красным подсвечиваются удалённые строки, зелёным добавленные. Есть общая статистика добавленных и удаленных строк. Возможность оставлять комментарии к любой строке диффа, а также к пулл-реквесту целом. Эта невероятно полезная возможность позволяет проводить инспекцию кода прямо в пулл-реквесте. Информация о новых коммитах в виде дерева. Автоматическая оценка возможности бесконфликтного слияния. Если оно невозможно, придётся вручную разрешать конфликты, как в обычном слиянии. Кнопки, чтобы слить или, наоборот, отклонить запрос. Изучив ваш пулл-реквест, владелец основного репозитория может выполнить его слияни (а может и нет). Отсюда и название: не вы "выталкиваете" (push) свои изменения в чужой репозитория, а уполномоченный пользователь их "затаскивает" (pull) в него.

вторник, 9 июля 2019 г.

Как правильно сделать merge

У меня вот так получились, что при слиянии ветки в мастер я получил конфликт. Я его пофиксил(мне так показалось) , но в итоге вообще все поламалось.
Я нашел последний нормальный коммит сделал от него ветку, допилил до нужного состояния и вот теперь она выглядит ровно так как мне нужно.
Теперь вопрос, у меня есть две ветки, одна мастер и вторая test
Мастер после мержа лежит поломанная и test которую я собрал заново.
Как теперь мне сделать мерж, чтоб мастер полностью забрал ветку test и не показывал мне конфликты?
Можно как то просто сказать, что теперь master будет test? Передвинуть указатель или что то в этом роде?


Ответ

Думаю, тут можно поступить так:
git checkout master git reset --hard commitName1 git merge test
где commitName1 - название того коммита из которого вы начали ветку test. Ветка master сольется с test.
Если в какой-то момент вы поняли, что закоммители плохой, ненужный или поломанный коммит, вы всегда можете сделать git reset --hard stableCommitName. Также важно помнить, что git reset --hard Переводит вашу ветку в указанное состояние, а все более новые изменения стираются. Чтобы обезапасить себя от потери чего-то нужного можно делать так:
git checkout master git reset --soft commitName1 git stash git merge test
эффект будет похожий, только более поздние изменения сохранятся в stash. Чтобы их вернуть, достаточно сделать git stash apply. И наконец, если вы потеряли коммит после reset --hard или rebase или еще как-нибудь, то его номер и название наверняка можно найти, сделав git reflog

понедельник, 17 июня 2019 г.

Перезаписать одного из предков для коммита слияния

Что есть:
Есть ветка C в которую вмержены ветки А и В.
* 113cfa6 (HEAD -> master) 12 * 74f6351 10 | * f63d30b (C) Merge branch 'B' into C | |\ | | * afe44c6 (B) 8 | | * 1da5826 7 | * | 3b5fa89 11 | * | 93d7b1d Merge branch 'A' into C | |\ \ |/ / / | * | 9023742 (A) 3 | * | 8e7ac5c 2 * | | eb15793 (X) 9 | |/ |/| * | 01ea56d 6 * | 11585f1 5 * | c8905ca 4 |/ * dc6c154 1
Что нужно:
Нужно перемотать ветку С на последний комит мастера
* 6099fa1 (C) Merge branch 'B' into C |\ | * afe44c6 (B) 8 | * 1da5826 7 * | b8a7ffd 11 * | 7f48be6 Merge branch 'A' into C |\ \ | * | 9023742 (A) 3 | * | 8e7ac5c 2 * | | 113cfa6 (HEAD -> master) 12 * | | 74f6351 10 * | | eb15793 (X) 9 | |/ |/| * | 01ea56d 6 * | 11585f1 5 * | c8905ca 4 |/ * dc6c154 1
Что пробовал:
git rebase master C Но это убивает все мердж комиты и ребейзит все комиты веток А и В на мастер
История:
Объясню откуда появились такие странные требования. master используется для получения актуальных данных из remoute, все поставки в него через pullrequest. Каждая отдельная ветка (А,В) это решения для определенного issue. В конце какого то периода создается ветка pr(С) в которую вмердживают несколько бранчей(А,В), создают pullrequest и запускают тесты. Тесты как всегда падают, и фиксы по возможности поставляют в те бранчи(А,В) которые вмерджены в pr(С). Но иногда возникают конфликты или фиксы невозможно добавить в бранчи(А,В), так появляются отдельные комиты (11) в ветке pr(С). Пока проходят фиксы ветка master уже убегает вперед и нужно подмержить изменения в ветку pr(C). Мерджи из мастера происходят так часто что в ветке pr(C) половина коммитов это подливка мастера, потом pullrequest принимается и мастер превращается в паутину "подливок из мастера". Появилась идея избежать ненужных мерджей с мастером, и было принято решение перематывать ветку pr(С) от последнего комита master вместо мерджа с ним.


Ответ

Вам нужна опция -p (--preserve-merges), она заставляет rebase не развёртывать мёржи, а сохранять их. На заметку: не рекомендуется эту опцию использовать вместе с -i (--interactive), а если уж использовать, то не переупорядочивать коммиты, иначе результат может быть неожиданным.
git rebase -p master C

понедельник, 3 июня 2019 г.

git pull accept theirs/ours

Можно ли как-то заставить git во время pull-а использовать стратегию слияния theirs для конкретной директории? Но если конфликты возникнут в других местах - пусть предоставить мне возможность решать.
Сейчас в голову приходит только такое: делаем hook, который отрабатывает после pull-а, и запускает git checkout --theirs {моя директория}


Ответ

на основе ответа: Simple tool to 'accept theirs' or 'accept mine' on a whole file using git

для частичной автоматизации можно, например, использовать псевдонимы:
$ git config --global alias.accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f" $ git config --global alias.accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f"
и при возникновении конфликта после git pull для файлов/каталогов, которые должны быть ours, выполнить:
$ git accept-ours -- файлы/каталоги ...
а для тех, что должны быть theirs
$ git accept-theirs -- файлы/каталоги ...

среда, 13 марта 2019 г.

Git. Удалить родителя из коммита или отменить слияние

Здравствуйте. Имеется следующая ветка:
* c9ec96c Some Changes in EG proj * 928b5ea Merge branch 'testHDFS' |\ | * 1504e3f Redact Task | * a9dffca Add xmlResult | * 82cd8fb EGp with MetaCode | * db93620 Add EG progect to test * | 536029f Redact Task * | 44cc081 Add xmlResult * | 370584a EGp with MetaCode * | 96c5388 Add EG progect to test |/ * 765ca4c v5HDFS * 5da3f2a v4HDFS * cedc686 v3HDFS * 28d0e1a v2HDFS * a6f9d63 v1HDFS * e5f373a v3 * 708e3b6 v2 * c89f76a First commit
Ответвление от 765ca4c появилось после попытки переписать e-mail автора коммитов. Затем последовало слияние двух одинаковых коммитов (возможно вовремя не слил все изменения с github). Необходимо удалить дублирующую ветку.
Были следующие попытки исправить ситуацию:
git rebase --onto c9ec96c 536029f как посоветовали здесь. Результат:
First, rewinding head to replay your work on top of it... Fast-forwarded HEAD to c9ec96c. git reset --hard 1504e3f дабы удалить коммит вовсе (принимая во внимание, что это может привести к плачевным последствиям)
UPD: Попробовал метод от @alexander barakin, вот что получилось:
git checkout c9ec96с git rebase -i 765ca4c
pick 96c5388 Add EG progect to test pick 370584a EGp with MetaCode pick 44cc081 Add xmlResult pick 536029f Redact Task pick db93620 Add EG progect to test pick 82cd8fb EGp with MetaCode pick a9dffca Add xmlResult pick 1504e3f Redact Task pick c9ec96c Some Changes in EG proj
Затем:
pick 96c5388 Add EG progect to test pick 370584a EGp with MetaCode pick 44cc081 Add xmlResult pick 536029f Redact Task pick c9ec96c Some Changes in EG proj :x
Successfully rebased and updated detached HEAD. git log --oneline --graph
* f647a1b Some Changes in EG proj * 536029f Redact Task * 44cc081 Add xmlResult * 370584a EGp with MetaCode * 96c5388 Add EG progect to test * 765ca4c v5HDFS * 5da3f2a v4HDFS * cedc686 v3HDFS * 28d0e1a v2HDFS * a6f9d63 v1HDFS * e5f373a v3 * 708e3b6 v2 * c89f76a First commit git checkout master
Warning: you are leaving 1 commit behind, not connected to any of your branches: f647a1b Some Changes in EG proj If you want to keep it by creating a new branch, this may be a good time to do so with: git branch f647a1b Switched to branch 'master' Your branch is up-to-date with 'origin/master'. git log --oneline --graph
* c9ec96c Some Changes in EG proj * 928b5ea Merge branch 'testHDFS' |\ | * 1504e3f Redact Task | * a9dffca Add xmlResult | * 82cd8fb EGp with MetaCode | * db93620 Add EG progect to test * | 536029f Redact Task * | 44cc081 Add xmlResult * | 370584a EGp with MetaCode * | 96c5388 Add EG progect to test |/ * 765ca4c v5HDFS * 5da3f2a v4HDFS * cedc686 v3HDFS * 28d0e1a v2HDFS * a6f9d63 v1HDFS
Я понимаю, что создалась новая ветка и я могу по хэшу переключиться на head. Но не понимаю почему не удалились старые коммиты. Пытался дропнуть их и через rebase и через reset. Если ввести команду rebase для f647a1b (пересчитанный коммит), то на него смотрят коммиты, которые "выше" c9ec96c. Видимо не до конца произошло перебазирование и появился конфликт.


Ответ

насколько я понял, вы хотите удалить четыре «продублированных» коммита (и коммит слияния).
для этого можно воспользоваться интерактивным вариантом команды rebase
$ git rebase -i коммит.до.разветвления

пример:
$ git log --oneline --graph * aabf478 7 * 5430d97 6 * 696565e bind |\ | * dff29c3 15 | * 5709144 14 | * 133cf40 13 * | 1807d0e 5 * | f61ce99 4 * | c5c42a9 3 |/ * c521dd2 2 * fd32efc 1
требуется, чтобы история выглядела так: 1 - 2 - 3 - 4 - 5 - 6 - 7, а коммиты с сообщениями 13, 14, 15 и bind — вообще убрать.
в данном случае коммит до разветвления — это коммит с сообщением 2 и хэшем c521dd2
$ git rebase -i c521dd2
откроется редактор со следующими строками (обратите внимания — коммита слияния с сообщением bind в этом списке нет (и не должно быть)):
pick c5c42a9 3 pick f61ce99 4 pick 1807d0e 5 pick 133cf40 13 pick 5709144 14 pick dff29c3 15 pick 5430d97 6 pick aabf478 7
надо просто удалить строки с сообщениями 13, 14, 15, чтобы остался такой список:
pick c5c42a9 3 pick f61ce99 4 pick 1807d0e 5 pick 5430d97 6 pick aabf478 7
сохраняем файл и закрываем редактор. git закончит работу и выдаст примерно следующее:
Successfully rebased and updated refs/heads/master.
теперь история выглядит так, как требовалось:
$ git log --oneline --graph * 894f56f 7 * 305ff84 6 * 1807d0e 5 * f61ce99 4 * c5c42a9 3 * c521dd2 2 * fd32efc 1
естественно, хэши у перезаписанных коммитов (с сообщениями 6 и 7) изменились. но «содержание» у них осталось прежним, и в рабочем каталоге сейчас та же «картина», что и до вызова rebase

среда, 27 февраля 2019 г.

Слияние в GIT и командная работа

Помогите, пожалуйста, разобраться с командной работой в Git. Пока работа настроена так: 2 программиста: 1 делает работу, другой проверяет.
Тот который делает получает таски, для выполнения каждого таска создает новую ветку после после того как выполнил задание пушит эту ветку на сервер, сливает ветку со своим мастером делает новую ветку для таска и т.д.
Проверяющий забирает ветки с сервера и делает проверку если все ок вливает их в мастер отправляет на сервер. Если сделаны ошибки возобновляет таск.
Это все как-то коряво, я думаю можно сделать лучше, подскажите как, наведите на правильный путь!
Сейчас проблемы возникают на этапе проверки при слиянии веток. Как можно слить только те комиты которые были сделаны в сливаемой ветке ?


Ответ

Как можно слить только те комиты которые были сделаны в сливаемой ветке ?
В git под термином «ветка» (branch) подразумевается указатель на коммит, а не набор коммитов, как в некоторых других системах управления версиями файлов.
Иными словами, это точка, а не отрезок
Вам требуется перенести несколько коммитов (отрезок), а для этого нужно указать две точки
К примеру: одобренная задача решалась в ветке task125, а предыдущая, пока не одобренная задача, решалась в ветке task124.
Тогда для включения (в текущую ветку) одобренных коммитов (отрезка между этими двумя точками) можно использовать такую, например, команду:
git cherry-pick task124..task125

четверг, 29 ноября 2018 г.

Важно ли использование --no-ff при слиянии веток?

При слиянии веток в git можно указать флаг --no-ff, который отключит fast-forward. Какие есть +/- --no-ff кроме возможности увидеть красивый график наследования веток? Где вы используете --no-ff?


Ответ

--no-ff удобен для реверта. Если много людей делают код и много коммитят в свои ветки (а в случае гита - это абсолютно нормально), то с включенным fast-forward история превратится в нечитаемое мессиво. И если потом нужно будет какой-то объем работ откатить, то это может быть сложно. Да, я знаю о том, что коммиты можно перегруппировать перед мерджем. Но некоторых нужно ещё научить этому.
В одном с моих проектов этот флаг установлен глобально по желанию менеджмента.

Слияние веток, в одной из которых файлы были не переименованы, а удалены и созданы в другом каталоге


В последнем коммите ветки hometype есть изменения, которые должны быть в ветке master, но влить ее в мастер не получается, потому что в коммите Rename были изменены названия пакетов, что в общем означает новое местоположение файла/класса.
Получается, что в ветке master файлы, для которых есть изменения в hometype, находятся в других местах.
Как их теперь объединить, если это вообще возможно?


Ответ

судя по всему, git «не знает» о произведённых (в ветке master) переименованиях, и не может «связать» изменения, произведённые в другой (hometype) ветке (со «старыми» файлами), с файлами «новыми».

один из возможных (но не самый «изящный» из) путей «влить» изменения из другой ветки (hometype) в основную — получить патч из изменений, внесённых в ветке hometype, вручную исправить в нём имена файлов, и «наложить» патч в основной ветке командой git apply файл.с.патчем (см. man git-apply).
совет: тренироваться лучше на тестовой ветке, создав её командой git checkout -b тестовая-ветка исходная-ветка

изменять надо будет такие примерно строки:
diff --git a/file1 b/file1 index 88621c5..af3bc11 100644 --- a/file1 +++ b/file1
здесь имя файла, которое надо будет вручную исправить — file1, оно встречается четыре раза, и все четыре его появления надо исправить. будьте внимательны: так как у вас были исправления, судя по всему, нескольких файлов, то блоков таких будет больше одного.

получить патч из изменений, внесённых commit-ом, зная его хэш, можно, например, так:
$ git diff хэш^ хэш
запись хэш^ означает в данном случае «родительский» (parent) commit для данного commit-а
см. man git-diff на предмет подробностей об этой команде и man gitrevisions о смысле ^ и подобных модификаторов.

в будущем я бы порекомендовал переименования файлов/каталогов делать отдельным коммитом (отдельным от изменения содержимого этих же файлов). тогда программа git без дополнительных указаний должна распознавать такие переименования.
другой путь решения озвученной в вопросе проблемы (он более «изящен», но требует довольно длинного описания) как раз и основывается на указании программе git, какую долю изменений в файле, «удалённом в одном месте и созданном в другом», следует считать переименованием. для команды merge это делается с помощью опции rename-threshold стратегии recursive. см. описание этой опции в man git-merge и опции -M в man git-diff

суббота, 6 октября 2018 г.

Как разрешается конфликт изменений при слиянии ветвей?

Диспозиция такая:
Есть две ветки. в каждой из них присутствует файл который редактировался (один и тот же).
При слиянии веток что произойдет с этим файлом?


Ответ

Если кратко: произойдет конфликт слияния (merge conflict) и его нужно будет как-то разрешить.
Для бинарных файлов: только выбрать версию А или Б (или другие, если octomerge).
Бывает, что бинарные файлы Git воспринимает как текстовые и тогда merge их необратимо портит. Это прежде всего относится к файлам office-форматов.
Для текстовых файлов: пара вариантов:
Вручную разрешить конфликты
После merge в файле появятся куски из обеих сливаемых версий, как-то так:
<<<<<<< HEAD содержимое файла из первой ветки ====== содержимое файла из второй ветки >>>>>>> otherbranch
Нужно будет вручную отредактировать конфликтный файл (или файлы), при этом не забывая удалить метки, оставленные Git (>>>>>>> otherbranch). Затем:
git add conflicting-file-name.txt git commit -m'merged A and B'
Выбрать одну из версий файла
Можно явным образом указать: какой файл выбирать. Подходит, только если одна из версий не нужна.
git checkout --ours a.txt git checkout --theirs a.txt git add a.txt git commit -m "added theirs"

Сделал вам тестовый репозиторий, чтобы сразу клонировать и посмотреть, как оно работает.
git clone https://github.com/NickVolynkin/git-merge-test.git cd git-merge-test git merge otherbranch open a.txt
В файле видны отметки, можете с ним теперь проделать вышеописанные действия.
Подробнее написано в книге Pro Git на русском. Ее обязательно нужно прочитать, прежде чем работать со слиянием веток. Фундаментальное понимание процесса ничем не заменить.
Потренироваться с ветвлением и слиянием можно тут: Learn Git Branching

среда, 3 октября 2018 г.

Зачем нужен pull request, если есть push?

На текущем проекте мне советовали загружать каждый таск так:
Создаем ветку по имени таска Комитим pull request - Отправляем все на удаленный репозиторий Далее мне советуют: "смотришь код и мерджишь"
Не совсем понятен четвертый пункт. Мне советуют для каждого таска ветвь создавать, заливать в нее изменения, и сливать обратно с master. Я понимаю, что репозитория два: локальный и удаленный.
Т.е. мне создавать на локальном ветку, коммитить, мержить и пушить на удаленный репозиторий? Перед этим всем скачать обновления с удаленного. Зачем тогда нужен pull request, если push и так отправляет данные в удаленный репозиторий?


Ответ

Организация работы, основанная на пулл-реквестах (pull-request, merge-request, запрос на слияние), характерна для распредленных проектов, которые размещаются на специальных хостингах репозиториев. Git сам по себе не имеет такого функционала, он реализуется именно хостингом. Кроме GitHub эту возможность предоставляет Gitlab, возможно есть и другие хостинги. Называется такая организация GitHub flow или Gitlab flow - в противоположность более традиционному Git flow git-flow ("flow" - поток).
Про организацию Git flow можно почитать в описании метки. Кратко: есть основная ветка master, разработчики создают ветки под конкретные задачи (фича, багфикс), потом сливают их в master. Возможно использование ветки-агрегатора develop, в которой копятся изменения до момента очередного релиза.
Git flow реализуем, когда у всех разработчиков есть право создавать новые ветки в удалённом репозитории. Это часто так при закрытой разработке внутри компании, но почти всегда не так, когда проект хостится открыто. Нельзя просто так взять и запушить свою ветку в чужой репозиторий на GitHub.
Другое важное право - сливать изменения в ветку master или другую, из которой код уходит в производство. В открытом репозитории это может делать владелец или группа уполномоченных пользователей. В закрытом код обычно может сливать ответственный за это сотрудник. Перед слиянием код может и должен проходить инспекцию и тестироваться. Если у вас не так - повод обеспокоиться.
Чтобы у разработчиков всё-таки была возможность принимать участие, коммитить свои изменения/дополнения и потом предлагать слить их в основную ветку проекта, были придуманы форки (fork, вилка). Форк - это ваша собственная копия целого репозитория Git. В ней вы можете создавать собственные ветки, делать новые коммиты и всё остальное, что можно делать с принадлежащим вам репозиторием.

Чтобы предложить добавить ваши изменения в основной репозиторий, используется пулл-реквест. Алгоритм создания такой:
Создаете локальную ветку. Создаете в ней новые коммиты (иначе нет смысла в слиянии). Пушите эту локальную ветку на удаленный репозиторий. Заходите на сайт хостинга репозиториев. Там выбираете одну из веток вашего удаленного репозитория и предлагаете влить её в одну из веток другого удалённого репозитория. Как вариант, если у вас есть право создавать ветки, но нет права сливать в master - можно создавать пулл-реквест внутри одного репозитория. Нажимаете кнопку подтверждения.
Теперь создаётся собственно пулл-реквест, как сущность. У него в том числе есть:
Номер и url. Он также появляется в списке открытых реквестов целевого репозитория. Информация о внесённых изменениях в формате diff. Красным подсвечиваются удалённые строки, зелёным добавленные. Есть общая статистика добавленных и удаленных строк.
Возможность оставлять комментарии к любой строке диффа, а также к пулл-реквесту в целом. Эта невероятно полезная возможность позволяет проводить инспекцию кода прямо в пулл-реквесте.
Информация о новых коммитах в виде дерева.
Автоматическая оценка возможности бесконфликтного слияния. Если оно невозможно, придётся вручную разрешать конфликты, как в обычном слиянии. Кнопки, чтобы слить или, наоборот, отклонить запрос.
Изучив ваш пулл-реквест, владелец основного репозитория может выполнить его слияние (а может и нет). Отсюда и название: не вы "выталкиваете" (push) свои изменения в чужой репозитория, а уполномоченный пользователь их "затаскивает" (pull) в него.