Обновить
59
Адам@capslocky

Software Engineer

0,1
Рейтинг
12
Подписчики
Отправить сообщение

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

Я попробовал "Обратный локальный мерж" на моем небольшом демо репозитории.

Во-первых, тут происходит схлопывание всей истории ветки в один коммит поверх ветки main. То есть по сути rebase + squash.

Во-вторых, мне пришлось явно выйти из мерджа:

% git switch -C feature
fatal: cannot switch branch while merging
Consider "git merge --quit" or "git worktree add".

% git merge --quit

И я также согласен, что форс-пуш лучше избегать. Можно изменить этот подход без потери истории, не создавая rebase, и не делая форс-пуш.

# уходим в detached state
git switch --detach origin/main

# мержим ветку в detached HEAD
git merge -n feature

# выходим из мерджа, решаем конфликты, добавляем файлы
git merge --quit
git add -A

# создаем временный коммит чтобы зафиксировать результат как HEAD
git commit -m "Temp commit"

# самый главный трюк: создаем merge commit используя HEAD с двумя парентами, полчаем его хэш и
# сразу переносим ветку на этот новый коммит (по сути fast-forward)
git switch -C feature $(git commit-tree HEAD^{tree} -p feature -p origin/main -m "Merged branch 'main' into 'feature'")

# обычный пуш без форса
git push origin feature

В общем я использовал тот же прием, про который писал на Хабре тут и тут.

Когда 3 года назад произошел большой взрыв технологии LLM, компьютеры Apple оказались единственными способными на быстрый inference моделей малого и среднего размера за счёт unified memory для CPU и GPU с колоссальной пропускной способностью. К сожалению, до сих пор нет нормальной альтернативы, а Mac Studio с большим объемом памяти просто убрали из продажи. Компания Apple опять на коне. Ещё бы была поддержка CUDA, то их рабочие станции стали бы золотым стандартом для исследователей и разработчиков в сфере AI.

Линус Торвальдс много раз объяснял почему Linux на C и в нём никогда не будет C++. И одна из причин было то, что он не хочет, чтобы код в его проекте писали C++ программисты. При этом Rust был им допущен и уже есть в исходниках Linux.

Каждый коммит в git описывает состояние проекта целиком и полностью, а видимый diff всегда вычисляется динамически. Коммит это дерево проекта (tree) + метаданные, более подробно в моей статье тут.

Слишком хорош для запуска LLM.

Более полный список интерфейсов

List<Integer> list = new ArrayList<>();
Deque<Integer> queue = new ArrayDeque<>();

Set<Integer> set = new HashSet<>();
Map<Integer, String> map = new HashMap<>();

NavigableSet<Integer> set = new TreeSet<>();
NavigableMap<Integer, String> map = new TreeMap<>();

Субъективно, Waymo ездит очень аккуратно, по всем правилам, но как робот, теряется в нетипичных ситуациях. Я думаю, что аварийность значительно меньше, чем у Uber.

Интересно, а что будет после его ухода и многолетней диктатуры? Демократия разработчиков? Олигополия больших корпораций? Добавят С++ или ZFS?

Если разработчик лично предпочитает merge, но на текущем проекте всем нужно делать rebase, то в таком случае данный метод это очень хороший компромисс.

И я согласен, что rebase требует большей квалификации и понимания, чем merge. И что rebase противоречит оригинальной идеологии git, что все коммиты должны быть иммутабельны.

Допустим, общая ветка (upstream) это develop, есть три варианта насколько строго требовать корректность коммитов в репозитории на сервере:

  1. develop должен быть корректным в любой момент времени.

  2. develop + feature ветки должны быть корректными в любой момент времени.

  3. все коммиты в истории всех веток должны быть корректными.

Первый вариант наиболее распространенный, дает больше свободы разработчикам и меньше давит на них.

Второй вариант имеет смысл если над feature веткой работают два разработчика одновременно, или когда ветка отдельно деплоится для тестирования.

Третий вариант самый строгий. В общем он естественный если только делать merge. Но в случае rebase всегда гарантировать синтаксическую и логическую корректность каждого rebase-нутого коммита становится очень сложно.

Мой метод rebase-а подходит для 1 и 2 вариантов: upstream всегда рабочий, все мерджи в upstream несут только корректный дифф, feature ветки тоже корректны в любой момент времени (можно сбилдить и протестировать).

Минус моего метода в том, что если сделать checkout какого-то промежуточного коммита, то он может не сбилдится, то есть 3 вариант отпадает. Только как правило в этом нет необходимости.

Я имел в виду, что работа по исправлению конфликтов становится одинаковой между merge и rebase в предельном случае, когда в ветке всего один коммит.

Есть несколько моментов. Допустим, на ветке 15 коммитов и она готова для merge-а. В общем случае, заранее неизвестно будут ли конфликты и в каком объеме. Если история коммитов не важна, то да, можно просто сквошить все 15 коммитов в один большой коммит, и там уже не важно merge или rebase, это будет один и тот же большой конфликт.

Но в большинстве случаев история отдельных коммитов важна, а точнее, их диффы и описание диффов. Однако каждый коммит может привести к отдельному конфликту при rebase. Обычно эти конфликты исправляются вручную по мере продвижения rebase-a, и целью является новый корректный код , что часто приводит к потере оригинального кода. Получается, что описание диффа старое, а код в нем новый, но это является нормой в классическом подходе. Из других минусов по сравнению с merge - нужно больше времени на исправление конфликтов и сложность в оценке суммарной работы.

Смысл данного метода в моментальной оценке работы по исправлению конфликтов и максимальная экономия времени на исправление, это достигается за счет merge-а. При этом сохраняется вся оригинальная история коммитов и оригинальный код, даже если он уже устарел. Это подходит не всем, и тогда нужен обычный rebase.

Обратный дифф не вычисляется, точнее после безусловного ребейза проект полностью заменяется корректным состоянием после сделанного merge-a, поэтому возникает дополнительный коммит. Но его легко убрать, соединив с предыдущим коммитом.

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

Xeon / EPYC это обычные CPU, поэтому скорость генерации токенов будет слишком медленная, по несколько секунд на одно слово, тогда как Apple Silicon это несколько слов в секунду. Энергопотребление тоже не в пользу Intel / AMD.

Фактически, компьютеры от Apple - единственные на рынке с большим объемом RAM памяти, которая доступна не только CPU, но и GPU. В общем, это и есть unified memory и это идеально подходит для локального LLM inference: чаты, кодинг.

Вместо git push --force лучше всегда делать git push --force-with-lease. В чем разница? Допустим вы с Васей работаете над одной общей веткой и хотите исправить текст нового коммита, который вы только что отправили, но если Вася в это время отправил свой коммит, то git push --force просто молча выкинет его коммит из истории на сервере, потому что ваш репозиторий его не видит. Тогда как git push --force-with-lease запрещает переписывание ветки, если там есть новые чужие коммиты. Я лично использую алиас git pf.

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

Согласен, я сам разработчик, так всегда и происходит. Только я никого не оправдываю и не обвиняю. Замедление скорости доставки под грузом старой архитектуры и качества кода - это, к сожалению, нормально. Бизнес редко выбирает риск переписывания системы с нуля.

Это практически все случаи, когда кому-то платят деньги за написание кода. В бизнесе компания вынуждена зарабатывать деньги, а расходы на разработку ПО - это большая и серьезная статья расходов, которую она стремится минимизировать. Только корпорации могут себе позволить такие большие затраты.

1
23 ...

Информация

В рейтинге
3 697-й
Откуда
Sunnyvale, California, США
Зарегистрирован
Активность