Git в домашнем хозяйстве. Часть 2: Уоу-уоу потише, не конфликтуй!



Всем привет.
Очень неожиданно, но предыдущая сумбурная и капитанская статья с простыми примерами о том, что Git — штука, в общем-то, не такая уж и замороченная, заслужила внимания. По-этому в этой я хочу раскрыть некоторые вопросы, освещенные в комментариях, а также привести какие-то примеры из жизни разработчиков, использующих Git по GitHub Flow.

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

Я использую Git + командная строка + SourceTree под MacOS и Ubuntu (в убунте xterm). И там и там работа абсолютно идентична.

Что ж, не будем медлить — вперед!

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

## Ветки. Что это? Ходим по веткам и коммитам.
Ветки — это цепочки коммитов. Любой коммит, как вы помните, характеризует состояние рабочей папки на каком-то этапе разработки.
Указатель на текущий коммит называется HEAD. То есть, когда вы перемещаетесь по коммитам, чтобы вернуть состояние рабочей папки в тот или иной вид, согласно этапам разработки, вы просто передвигаете указатель HEAD на тот или иной коммит. Указатель передвигается командой git checkout. В качестве параметра мы можем указать хеш коммита, тэг, название ветки (тогда мы окажемся на самом конце ветки), или указатель HEAD и «крышечки», то есть, чтобы уйти на 5 коммитов назад можно написать HEAD^^^^^. На самом деле есть еще другие параметры, но о них читайте в доках — в 95% случаев хватает поиска по хэшику или переход назад на количество «крышечек».

Эмпирично на картинке это выглядит так:
Branches
1. У нас одна ветка и указатель HEAD на самом верху.
2. Мы решаем уйти на 2 коммита назад и создать ветку.
Для этого переводим указатель HEAD на 2 коммита назад (если промахнулись, то стОит вернуться командой git checkout master, и попробовать еще раз):
git checkout HEAD^^


И создаем новую ветку:
git checkout -b new-branch

Здесь checkout -b означает создать ветку и сразу перейти на нее (перенести на нее указатель HEAD). При создании ветки не создается новый коммит — то есть мы находимся на коммите, который находится в мастере. Ну оно и понятно — мы же собираемся пилить ветку из какого-то исходного состояния рабочей папки, вот мы это состояние и определяем стартом новой ветки.

Запушить локально созданную ветку в удаленный репозиторий можно командой:
git push origin new-branch

На сервере будет создана ветка origin/new-branch, и наша локальная ветка будет за ней следить. И, собственно, пушить ветку в удаленный репозиторий нужно этой командой.
Да, локальная ветка и удаленная — разные вещи.
Я знаю, что здесь кроется тонна непоняток, но, думаю, вы разберетесь с этим сами)

3. Работаем в ветке.
Работая в ветке, мы создаем цепочку коммитов, которые уводят нас все дальше от исходного состояния рабочей папки. Что мы и видим из рисунка.

4. Удаляем ветки.
Чтобы удалить ветку, содержимое которой уже слито в другую ветку, можно использовать команду:
git branch -d branch-name


Если вы хотите удалить ветку, содержимое которой не слито в другую ветку (а это значит потерять код из этой ветки), используйте команду с ключом в виде большой буквы D:
git branch -D branch-name


## Соединяем ветки. Merge и Rebase.
Сначала немного рисунков на бумаге.
Из предыдущего рисунка видно, что мы сделали какие-то изменения в new-branch и мы хотим вернуть эти изменения в master.
Это можно сделать командой merge.

merge
То есть мы делаем 2 действия:
1. Переключаемся на ветку КУДА будем мержить. В данном случае в ветку master.
git checkout master


2. Мёржим:
git merge new-branch

В результате мержа создается новый коммит, который автоматически подписывается комментарием (типа ветка такая-то смержена с такой-то). Этот коммит создается в ветке, КУДА мы мержили, и HEAD сдвигается на этот коммит — то есть мы оказываемся на верхушечке.
Если изменения в ветке new-branch сделаны только в тех местах, где не было изменений в master, то git сам все сделает правильно. Если изменения были в одних и тех же местах в обоих ветках, то будет merge conflict, но об этом чуть позже.

Если вы в результате неправильного мержа что-то поломали, или просто опрометчиво смержили то всегда можно откатить состояние репозитория на коммит назад, находясь на коммите мержа:
git reset --hard HEAD^

То есть мы говорим: гит, давай-ка ресетни состояние репозитория до предыдущего коммита, при этом измени состояние рабочей папки до состояния предыдущего коммита (это ключ --hard).

Теперь другая история. Делаем rebase.
Ребэйз — это такая операция, которая изменяет откуда растет ветка. Например, мы отбранчевались от мастера, написали свою фичу, а в это время другой разработчик вмержил в мастер свою фичу. Мы можем сделать так, чтобы наша ветка стала вся полностью произрастать из нового коммита в мастере при помощи команды rebase.

rebase
Здесь тоже все без магии. На картинке ветка new-branch стартует с 3-его коммита master, а мы хотим, чтобы она стартовала с самого крайнего — 5-ого — коммита.
1. Сначала переключаемся на ветку, которую хотим ребэйзить:
git checkout new-branch


2. Делаем ребэйз на master (то есть = на самый верхний коммит ветки master):
git rebase master
Ребэйз происходит очень просто. Сначала переносится 1-ый коммит из ребэйзимой (ой, словечко-то какое) ветки на новое место. Следом за ним — второй, потом третий и так далее. И если в каком-то из коммитов есть изменения в тех же местах, что и в новых коммитах мастера, то нужно будет разрешить merge conflict. При этом процесс rebase останавливается, вы разрешаете конфликт, и для продолжения процесса в консоли пишете:
git rebase --continue

Если вы решили отказаться от текущего ребэйза, пишите в консоли:
git rebase --abort


## Разрешаем любые конфликты недорого.
И мы плавно переходим к вопросу разрешения конфликтов. Это тема больная, особенно для файлов проектов (то есть для Xcode это, например, *.xcodeproj, и сломать его в результате мержа — как два пальца об асфальт) или для изменяемых ресурсов.
Но для исходных кодов все обычно решается легче легкого.
Будет 100500 картинок, но не пугайтесь.

Предположим, что есть два разработчика (Asa и Akira), которым нужно поработать над общим файлом main.c, который сейчас выглядит вот так:
Исходный master main.c

Исходное дерево проекта выглядит так:
Start master tree

Asa
И, допустим, Asa бранчует из текущего мастера ветку, и меняет main.c за несколько коммитов.
В командной строке это выглядит цепочкой команд добавления нужных файлов в коммит и добавления коммитов (да, эта картиночка для того, чтобы показать, что командная строка вовсе и не хард-кор, а вполне себе годный и удобный инструмент, особенно, когда приходится писать много кода, много пользоваться hot-key'ами, и привыкаешь не смотреть на клавиатуру).
Asa single commit

Код main.c в ветке Asa стал выглядеть вот так:
Asa-after-coding

Akira
В это же самое время Akira бранчует свою ветку с того же самого мастера, что и Asa.
И просто вычищает все, что в проекте не пригодится за пару коммитов и приводит вид кода к принятому гайдлайну.
В итоге в её ветке код выглядит так:
Akira-after-coding

С чего-то поменялся мастер.
В это время прямо в мастере какой-то хрен добавляет в Main.c Copyright. Это могло случиться в результате того, что в мастер вмержили ветку, в которой закончили разработку раньше, чем в ветках Asa и Akira.

И в итоге мы получаем вот такое состояние веток в репозитории:
Asa Akira Master repo after merging

Что делать, Akira? Надо мёржить)
Допустим, первой в мастер мёржить стала Akira. Она сделала это просто командой merge (ай-ай-ай! Плохая Akira!) вот так, и напоролась на конфликт:
Akira merge conflict

В SourceTree мы видим, как появились какие-то незакоммиченные изменения. Эти изменения создал сам git, чтобы обозначить, что его смутило в файлах. Недолго думая, находим в списке файл с восклицательным знаком — это значит, там есть конфликты, нажимаем по нему правой клавишей мыши, выбираем Resolve Conflicts -> Launch External Tool.
Launch External Merge Tool

Открывается утилита разрешения мерж конфликтов. Она выглядит, как 3 текстовых редактора в одном — сверху два, и снизу один. Сверху слева — что было в мастере, справа — что у вас (точнее, сейчас у Akira), снизу = что будет в итоге. Снизу справа выбор Actions для быстрого выбора — оставить то, сто справа, слева, оба и т.д. Нам нужно оставить изменения из мастера про Copyright, поэтому просто выбираем оставить то, что слева.
Akira resolve conflicts

Сохраняем и выходим (нажимаем Cmd+s, потом Cmd+q).
Конфликт разрешен, больше конфликтов нет, зато появился файл main.c.orig — это просто копия файла до разрешения конфликта. Я их сразу удаляю на фиг.
Теперь вручную закоммитим изменения:
git commit


В появившемся vim-е просто набираем ESC, пишем :wq для выхода с сохранением, так как за нас все уже заполнено, и жмем ентер — всё, смержили.

Asa и rebase.
Asa пошла другим путем — она решила заюзать rebase — то есть сделать так, как будто ее ветка стартовала с крайнего в мастере коммита — с мержа Akira. Она делает вот что, и напарывается на конфликт:
Asa rebase conflict 1

Но не нужно отчаиваться, просто открываем SourceTree, там открываем Merge Tool, как и в прошлый раз, нажимаем Cmd+D (найти следующий конфликт). Видим картину:
Asa merge tool 1

Всего лишь надо выбрать префиксного или постфиксного инкремента. Выбираем правую часть, потому что так хочется. Привычные Cmd+s, Cmd+q.
SourceTree показывает, что проблем больше нет, можно продолжать процедуру rebase.
git rebase --continue


И, черт побери, опять конфликт!
Asa rebase conflict 2

Но мы уже знаем что делать. SourceTree->Resolve Conflicts->External Tool. Видим картину:
Asa conflict 2 resolve
Хехх, а тут надо чуточку подумать.
Было:
trace_puts("Hello ARM World!");

У нас:
// Send a greeting to the trace device (skipped on Release).
 trace_puts("Hello ARM World! My name is Asa!");


Надо оставить свою часть, но при этом удалить комментарий. Что мы и делаем. Переходим к следующему конфликту по Cmd+d.
Asa merge tool 2-2
Конфликт, очевидно, решим в точности так же, как и предыдущий. Конфликтов больше нет. Cmd+s, Cmd+q.
git rebase --continue


На этот раз все заканчивается благополучно, видим завершение rebase в консоли:
Rebase successful done

Теперь посмотрим что стало с нашим деревом коммитов.
Commit tree after rebase

Если присмотреться, теперь наша ветка asa торчит ровно из крайнего коммита master, как мы и предполагали.
Если мы захотим запушить ветку после ребэйза, нужно применить следующую команду:
git push --force origin asa

То есть заставить удаленный репозиторий полностью переписать свою ветку asa нашей веткой asa.

Теперь в идеале надо удалить ветку akira, схлопнуть ветку asa до одного коммита с помощью команды git rebase -i, и вмержить получившийся коммит в master. Тогда история в master будет красивая и линейная. Но, хоть это и не сложно, но я хочу спать, так что в следующий раз.

P.S.
В следующей части думаю описать еще следующие штуки (если, конечно, это требуется):
1. Возвращение из стейджа. Хождение по коммитам. Кейс: 1 файл откатить назад на 2 версии, отредактировать, впилить в мастер.
2. В ответ на комментарий про Роскомнадзор и поднятие своей системы контроля версий хочу рассказать, что делать, если удаленный репозиторий более недоступен, а работать надо. Как можно все сделать в локальной сети или даже локально на машине.
3. Зачем нужно выбирать язык в GitHub (и наверное в BitBucket), и про .gitignore.

Комментарии (103)

RSS свернуть / развернуть
linux и mac настолько суровы, что сделать иллюстрации можно только руками на бумаге? ;)
+5
  • avatar
  • ZiB
  • 07 февраля 2015, 07:33
Ой, да ладно!

Я тоже люблю почеркаться руками на бумаге, а потом зафотать. Ичо?

В рисунках от-руки есть некий радиолюбительский шарм, который, похоже Вам не нравится. Я так понимаю, что для передачи информации (знаний, опыта) важно ведь, не то, как выглядит схема или граф алгоритма, а то, чтобы это изображение было понятно и прозрачно.

Но если нужны шашечки, а куда ехать — не важно, то, наверно, — да, важно качество изображения. На саму суть того, что хотел донести автор, можно как бы забить. Главное фантики-бантики, перделки-свистелки. Поэтому и наезды на Линукс.

А Злому Покемону — спасибо! Приятно было почитать.

Давно уже тлеет желание написать практическое руководство по работе с Гит-ом, но как-то в последнее время вообще времени ни на что не остается. Даже свой блог я начал «запускать», одну политику гоню, а темы электроники, программирования, Линукса начали зарастать паутиной забвения.

Еще раз спасибо Покемону — ты сделал то, на что я не смог подняться. Уважуха и респект!
0
Вопрос не имел подтекста в поднятии споров или желания обидеть автора, просто стало интересно «почему?»
Ведь рисунки очень просты.

В ступать в полемику о Git, Linux, Windows да и вообще о чем либо я не хочу.
Хотя я сам использую Git, Linux и Windows очень давно и они мне все нравиться. Каждый чем-то своим :)
0
я могу сказать только за себя. Мне проще и быстрее сделать рисунки от руки, а затем их сфотать, чем долго-долго-качественно-соблюдая равнения вырисовывать их в Paint-е или в Dia.

То есть, если нужно сделать качественно типа Отчет, ТЗ или еще какой-то производственный документ (для студентов — диплом, курсач и т.д.), то рисую с помощью указанных программ. А если нужно сделать быстро, для таких же товарищей, как и я сам, и при этом «кружавчики на трусиках» не нужны никому, то у меня быстрее получается начеркать на листочке бумаги и зафотать.

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

Кстати, я как-то видел на просторах тырнета книжку, где рисунки были сделаны именно в таком стиле — карандашом на бумаге, а потом вставлены в текст в виде фоток. И я не заметил какой-то разницы в том, что информация в книжке исказилась.
0
Это от незнания и неумения работать с инструментами — есть простые программы типа MS Word :)
И красиво и опрятно и легко вносятся изменения и Заказчик понимает, что имеет дело с Профессионалом, а не с «командной строкой»
0
Нет, это от нежелания заниматься херней — у вас-то для этого, я посмотрю, времени — завались)
Но так не у всех)
Мне нравится делать какие-то наброски — рядом постоянно лежит блокнот с карандашом. Зачем мне лишний раз тыкать в профессиональный инструмент ворд (кстати, вбейте в гугл OmniGraffle), если можно быстрее, веселее, и неформальнее (что более соответствует атмосфере блога) нарисовать, щелкнуть айфончиком (это такой телефон, в котором камера есть), оттуда рисуночек автоматом подсосется Dropbox'ом, и я его тут же порежу в фотошопе, как мне надо)
Да уж, мы — дилетанты, в отличие от вас, дорогой и профессиональный пиэлсист-тракторист, совершенно не могём в мышку)
0
Пальцы не растопыривай своим «айфоном» — если есть «инструмент», то используй его, а не размещай нечёткие серые самострелы…
Я в Visio блок-схемы рисовал, когда твоего айфона и в проектах не было :)
Кстати на некрутых телефонах можно даже пальцем рисовать без бумаги и карандашей
Я активно пользуюсь активными заметками и пальцевым редактированием отснятых фотографий… рекомендую, ведь я не злой, потому что у меня есть нормальный телефон и Windows :)
0
а не размещай нечёткие серые самострелы…
Самострелы? В смысле Selfie?
Нет, картинка сверху — это не самострел, и даже не фотография — она просто нарисована.

Я в Visio блок-схемы рисовал, когда твоего айфона
Да, кстати, на улице уж 2015 год, а вы все о тех временах судачите) Ну кому это интересно?

Кстати на некрутых телефонах можно даже пальцем рисовать без бумаги и карандашей
А из булки хлеба вылепить троллейбус.

пальцевым редактированием отснятых фотографий…
Хмм, вы освоили Instagram? Похвально!)

А вы не находите, что заметки на экране вашего телефона выглядят весьма гаденько? Ну или у вас почерк плохой, или на бумажке карандашом реально удобнее рисовать)

нормальный телефон и Windows
Хехх, слишком толсто. Наброс не засчитан.
Вы ж наверняка не знаете даже про внутренности IDE, которой пользуетесь, не то что архитектурные отличия платформ и подходы для разработки под них)
0
В рисунках от руки свой шарм, но есть и пара проблем:
1) Разборчивость текста
2) Контрастность картинки
Ты бы их хоть отсканировал или в B&W сконвертировал (хотя я в свое время так и не нашел, чем сконвертировать фотку рисунка карандашом так, чтобы получился результат, аналогичный сканированию в BW режиме) — тогда бы получился рисунок в стиле приведенного well-man2000. Там действительно прикольно выглядит и никаких нареканий к «серым по серому».
0
Ну, как бы у меня нет Виндовса от слова вообще. Это во первых.

А во вторых, сама идея использовать программные инструменты не по назначению — ну, это как-то от Лукавого что ли. Конечно, можно из буханки хлеба…
-1
я как-то видел на просторах тырнета книжку, где рисунки были сделаны именно в таком стиле — карандашом на бумаге
Getting Started in Electronics.
Презабавная книжечка. :-)
0
Скачал. Полистал. Да, презабавная книжица.
Такое ощущение, что это конспект лекций для студентов какого-то преподавателя.
Но всё равно спасибо! Я получил положительные эмоции, за это и спасибо.

Несколькими постами выше, когда говорил о книге, я имел ввиду книгу «Linkers and Loaders» norfs.sourceforge.net/linkers_and_loaders.pdf
0
Wow! Нет слов — я потрясен!


Он ее 11 лет писал…
Особенно умилила надпись: PRINTED IN THE UNITED STATES OF AMERICA!!!
0
Да не, просто люблю чиркать карандашом по бумаге)
В linux у меня, кстати, реально даже нет программ для рисования — ну он в виртуалке крутится, я его использую только там, где без него никак))
+2
Пользуясь случаем хочу спросить адекватный свободный инструмент для Мерджа под Виндоус. Кто каким пользуется?
0
KDiff3.

P.S. А что это за такая любопытная мержилка на скринах? Несколько напоминает перфорсовскую.
0
P.S. WinMerge еще пользую, но он не 3-way.
0
Чето никогда не задумывался о мержилке — сейчас заглянул в настройки SourceTree.
Та, что на скринах — выбрана и называется FileMerge, но доступны и другие. Надо будет хоть попробовать их поюзать)

SourceTree merge tool preferences
0
FileMerge — кусок Xcode? Жаль, выглядит прикольно, но под другие платформы наверняка отсутствует.
0
Из остальных — araxis здоровый и платный, diffmerge выглядит примерно как KDiff3 (но, вроде, не открытый), kaleidoscope маковый, P4 емнип выглядит примерно как filemerge, но не без заморочек с лицензиями (и чем-то еще, ЕМНИП, не понравился в свое время).
0
Да, действительно, FileMerge — это тулза из Xcode.
0
Emacs же.
+1
Может пропустил в тексте.
Вопрос: как убрать старые commit (например что бы история начиналась с -2 коммита от текущего)?
Пользую Araxis Merge — вполне устраивает
0
  • avatar
  • x893
  • 07 февраля 2015, 12:10
Да, я не акцентировал на этом внимания, но упомянул.
Нужно написать:
git reset --hard HEAD^^
Количество крышечек = количество коммитов, которые нужно сбросить. Эти коммиты будет довольно сложно восстановить, так как они пропадут из дерева (но останутся в git-е до запуска garbage collector'а).
0
Эта команда двигает HEAD назад.
Я немного про другое. Например есть

HEAD
commit 4
commit 3
commit 2
commit 1 (initial)

я хочу что бы было
HEAD (те же файлы что и в HEAD выше)
commit 4
commit 3 (становится initial)

Удаляются commit 2 и commit 1 навсегда и безвозвратно.
0
Тогда надо юзать git rebase -i — это интерактивный ребэйз, и там есть опции для каждого коммита при ребэйзе.
То есть на самом деле нужно не удалить коммиты (их вообще удалить нельзя, потому что тогда разрушится дерево — у потомков будут ссылки на родительский коммит, но родительского коммита не будет), а схлопнуть часть коммитов в один. Для схлопывания можно выбрать опцию -s (это уже при rebase -i) или -f. При -s = коммит объединится с другим, и останется commit message, при -f commit message удалится.
0
Спасибо попробую.
По идее надо взять commit2 примениять его к commit1 и сделать родительским. и так до commit3. Просто думал есть одна команда в git для этого.
0
Хмм, ну в общем идея такая.

Вот было состояние репозитория:
1

Потом я беру и делаю:
git rebase -i 58d7b7c

Где 58d7b7c — хэшик коммита HEAD-2

Дальше выбираем что нужно делать с коммитами:
2
Коммиты здесь отображены не так, как на дереве, а вверх ногами)
Верхний я оставил pick, два нижних s.
Потом надо ввести новый commit message получившегося коммита (причем это не новый коммит, а именно сумма тех коммитов в одном).

Я оставил старое название коммита, который был с опцией pick, и в итоге получилось такое состояние репо:
3
0
То есть при:
commit 4 HEAD
commit 3
commit 2
commit 1 (initial)

Нужно перенести указатель HEAD на commit 3 (git checkout HEAD^).

Получится состояние:
commit 4
commit 3 HEAD
commit 2
commit 1 (initial)

И теперь сделать git rebase -i [хэш коммита 1]

Вроде как-то так.
0
В общем не правильно делает. да бог с ней с командной строкой, vin'ом. Проще новый репо создать и закоммитить.
0
Командная строка… кривые растопыренные пальцы… Мак… Линух…
Надо оставить свою часть, но при этом удалить комментарий. Что мы и делаем.
Глупее чем удалить комментарий придумать трудно :(
А потом думай нахера тут стоит Хелло Ворд // Send a greeting to the trace device (skipped on Release).
Никакие Гиты и Зиты (рюшечки) вам не помогут, если вы или ваши коллективные подельщики не будете писать подробные комментарии по ходу изменения кода.
Я ZIPую папки проектов по датам и потом всегда имею точку отката и верный исходник.
-4
Комментарии – это вообще «священный грааль» в программировании.
0
Комментарии, это всего лишь средство поместить в код дополнительную информацию. Это средство а не цель, и на «священный грааль» никак не тянет. Уместное применение комментариев, безусловно, облегчает работу с кодом. Но, во многих случаях есть более выразительные средства для привязки метаинформации. Например, атрибуты в С#, как частный случай АОП.
+1
Вы рассматриваете «священный грааль» как цель, что, несомненно, верно в контексте крестового похода в страны неверных. Но в тут это скорее метафора good practice, чем цель. Нравится вам писать код без комментариев – да на здоровье, пишите.
-1
Но в тут это скорее метафора good practice, чем цель. Нравится вам писать код без комментариев – да на здоровье, пишите.

Дело не в том, нравится или нет мне писать комментарии. И наличие/отсутствие комментариев не говорит о «good practice» написания кода.
Нужно максимально избегать написания такого кода, который бы нажался в комментариях. Делать код самодокументированным.
+1
Вас это беспокоит? Вы хотите об этом поговорить?
-1
Нет, не беспокоит :) Но я действительно хочу об этом поговорить, т. к. многие переоценивают наличие комментариев в коде.
Повторюсь, современные ЯП дают возможность программисту выражать свои намерения в рамках синтаксиса ЯП. Код должен быть самодокументированным. Комментарии (в реальном коде) нужны в достаточно редких случаях, это скорее исключение, чем правило (good practice,).
+2
OMG…
-1
Ну а если говорить серьёзно: почему вы вдруг решили, что моё замечание про обязательность комментирования == призыву комментировать каждую строку кода?
0
Возможно, я не так понял вшу фразу «священный грааль», но
обязательность комментирования == призыву комментировать
нет, ни в одном современном подходе к написанию кода такой вещи как «обязательность комментирования», наоборот, от комментариев хотят максимально избавиться …
0
Упс…
… такой вещи как «обязательность комментирования» нет…
0
Понимаете в чём тут дело… Комментарии обязательны как средство повышения понятности кода. Есть такая прикладная штука, называется сопровождение программного обеспечения. Вот комментарии к ней самым непосредственным образом и относятся. Если кусок кода понятен и так – замечательно. Но если там есть нечто, что спустя полгода-год может потребовать «поскрипеть извилинами», чтобы всё вспомнить и разложить (откуда что взялось и т.п.) – то лучше добавить комментарии. Равно как и откомментировать назначение функций и процедур.

Нет, можно, конечно, продолжать ломать копья… Но мне еще в 1981 объяснили, что так – правильно. И последующая работа утвердила в этом мнении. И как-то не вижу смысла от этой парадигмы отступать даже сейчас.
0
У МакКоннелла довольно большая глава посвящена комментированию.
Если кратко, то:
1) Лучше сделать код понятнее, чем прокомментировать его. Даже хороший комментарий не сделает мутный код понятным и поддерживаемым.
2) Комментарий должен говорить то, что нельзя узнать непосредственно из кода, и отвечать на вопрос «зачем», а не «как».
3) Плохие комментарии только вредят. А таких, честно говоря, большинство.
+2
Но если там есть нечто, что спустя полгода-год может потребовать «поскрипеть извилинами»
… значит это «нечто» — отличный претендент на рефакторинг. В большинстве случаев это «нечто» можно (и нужно) переписать так, чтобы код был понятен без «скрипа извилин» и дополнительных комментариев. А вот оставить это «нечто» в коде (даже при наличии множеств развернутых комментариев) – это, как раз, плохая идея.

Повторюсь, я не говорю, что комментарии вообще не нужны. Они нужны, но достаточно редко.
+2
значит это «нечто» — отличный претендент на рефакторинг. В большинстве случаев это «нечто» можно (и нужно) переписать так, чтобы код был понятен без «скрипа извилин» и дополнительных комментариев. А вот оставить это «нечто» в коде (даже при наличии множеств развернутых комментариев) – это, как раз, плохая идея.
Комментариями могут быть, например, ссылки на внешние источники и т.п. Да мало ли. Вообще, слухи о самодокументируемости кода сильно преувеличены. Тут вот выше книгу МакКоннелла упомянули. Ну так ровно те же самые советы имели место и хождение и раньше. Но при этом никто не утверждал, что подробные комментарии – это плохо. Просто комментарий должен быть информативным. Но всякое обсуждение в Интернете априори сводится к аксиоматике «оппонент – нуб» и начинается битва Капитанов Очевидность. Всё, мне эта «сказка про белого бычка, что начинается с чёрного бочка» надоела. full stop :)
+1
Но при этом никто не утверждал, что подробные комментарии – это плохо.
Как раз у МакКоннелла можно сделать вывод, что избыточное комментирование — это плохо.
И нередко у отстаивающих комментарии как раз того типа код и того типа комментарии, которые МакКоннелл называет вредными.
+1
Пфф, чувак, выдохни)

Если прогрммист не в состоянии сходу понять строчку кода вида:
trace_puts("Hello ARM World! My name is Asa!");

… то ему эмм, стоит поискать другое призвание)

Оставлять капитанские комменты в местах, где из кода однозначно понятно что происходит — это плохо.
Засоряет исходный код, код пухнет, его становится тяжелее читать, а значит поддерживать. То есть вы в этом случае пишите объективно плохой код.
trace_puts — это, очевидно, логирование действий, и если к логированию писать еще и коммент, то почему бы не пойти дальше и не писать комменты вида:
// Init i by five
int i = 5;
// Increment i
i++;
// Store i to m
m = i;

Эти комментарии бесполезны и не нужны.
Вообще у Макконнелла это все отлично расписано, рекомендую к прочтению.

И да, про папки и zip'ы.
Это кажется удобным, пока вы не научились работать с VCS и не делали реально больших продуктов — когда надо _поддерживать_ несколько версий для нескольких платформ, например.
Так что этим гордиться ваще не надо — ИМХО, если вы считаете себя профессионалом, вы можете использовать зипованный папки с исходниками от лени и отсутствия тяги к самообразованию, а иногда даже самодурства, уж простите за мое мнение (сам таким был, знаю).
+2
Эти комментарии бесполезны и не нужны.
Реально?
и что я пойму через месяц в чём смысл данного присваивания
// Store i to m
m = i;
// Store i to m_Состояние_Привода
m_Drive_Status = i; // Это ТУПАЯ ОПЕРАЦИЯ для запутывания Заказчика

Тут некоторые больше заботятся от кручении пальцев в командной строке, чем о смысле и наглядности кода для себя или других
про папки и zip'ы.
Это кажется удобным, пока вы не научились работать с VCS и не делали реально больших продуктов — когда надо _поддерживать_ несколько версий для нескольких платформ, например.
Да хоть для нескольких реальных объектов :)
Вот пример ввода объекта в работу и последующее сопровождение и добавление функциональности по просьбе Заказчика

жалею, что не всегда добавляю комментарии по CTRL+Z в описание архива и приходится лезть в комментарии шапки в самом архиве для понимания изменений
0
Реально.
Комментарии, которые говорят меньше, чем написанный код — не нужны как факт. Именно это я и демонстрировал в примере)
Если вы нормально спроектировали архитектуру проекта, то код у вас будет выглядеть, например, как:

/*! Где-то в хидере тип статуса привода */
typedef enum {
    DriveStatusReady = 0,
    DriveStatusBusy  = 1,
    DriveStatusHold  = 2,
    DriveStatusError = -1,
} DriveStatus;

struct Drive {
    DriveStatus status;
};

/*! В хидере с прототипом функции вы пишете бодрый комментарий, что делает функция */
void updateCurrentDriveStatusWithStatus(DriveStatus status)
{
    struct Drive currentDrive = getCurrentDrive();
    currentDrive.status = status;
}

int main
{
    ...
    updateCurrentDriveStatusWithStatus(DriveStatusReady);
    ...
}


Никаких тупых операций для запутывания заказчика)
Код, на мой взгляд, читаемый. Да, у меня есть некоторое ООП головного мозга, но подобный код поддерживать совсем не сложно.

Да хоть для нескольких реальных объектов :)
Что за бред?

А если вас попросят написать проект с поддержкой процессоров STM32, Atmel, PIC, и еще парочки других, при этом для каждой платформы в процессе работы рождается ветка 1, 2 и 3, которые начинают по тихой независимо друг от друга развиваться, при этом используя общую часть бизнес-логики. А потом вы понимаете, что для каждой платформы надо написать местами общие тесты, сделать внутренние дебажные версии, и при этом, желательно, не упороться)
У вас будет N[платформ]*M[веток]*K[таргетов]*V[релизных версий]? А если вас попросят релизить их с частотой раз в пару недель, а не 2 раза в год?)

Кароче я вот к чему:
Вам это кажется простым просто потому что проекты — маленькие. Вы видимо пилите их в одну каску, вот вам всё и нравится) А вообще это называется — заниматься хернёй) Сам занимался — знаю)
+3
Пфф, чувак, выдохни)
жаргон и стиль растопырщиков :(
Теперь по прошествии часа ты начал давать осмысленные имена переменным и вписывать комментарии, как будто глупости написанные тобой ранее исчезли.
Вам это кажется простым просто потому что проекты — маленькие. Вы видимо пилите их в одну каску, вот вам всё и нравится
Размер ZIPа видел?
А если вас попросят написать проект с поддержкой процессоров STM32, Atmel, PIC, и еще парочки других
STM32, Atmel, PIC, и еще парочки других в одном проекте да ещё и на одной плате?
А вообще это ^^^ называется — заниматься хернёй :)
Сам не занимался такой — но теперь знаю таких :)
-1
жаргон и стиль растопырщиков :(
В точку!

Теперь по прошествии часа ты начал давать осмысленные имена переменным и вписывать комментарии, как будто глупости написанные тобой ранее исчезли.
До жирафа тоже долго доходит.

Размер ZIPа видел?
Охохо, аж 60 мегабайт! Это же в байтах там циферки?
Нет, я имел ввиду большие проекты.
Например, сейчас папка проекта, над которым я работаю с командой на работе занимает около 20Гб. На самом деле больше и растет, потому что еще не все сделано. Собирается он с нуля около 10 минут на MacBook с i5 на борту и SSD, потому что с HDD минут 25.

STM32, Atmel, PIC, и еще парочки других в одном проекте да ещё и на одной плате?
Да, представляешь, например freeRTOS разрабатывается примерно в подобном ключе. Ну или uClinux. Не видел исходники uClinux'а? Тогда прощаю «да ещё и на одной плате»)))

Сам не занимался такой — но теперь знаю таких :)
Вот, кстати, вопрос — а чем вы вообще занимаетесь, раз позиционируете себя этаким гуру в области информационных технологий, и с жаром отстаиваете право на собственное невежество?
+2
Например, сейчас папка проекта, над которым я работаю с командой на работе занимает около 20Гб.
20 ГБ для STM32, Atmel, PIC?
И это хранить в потенциально санкционно-забаненном Облаке?
Реально только самострелы так делают :)
а чем вы вообще занимаетесь, раз позиционируете себя этаким гуру в области информационных технологий
я не знаю, что такое «информационные технологии» и что такое «гуру».
Всех заявляющих, что они IT посылаю посмотреть первую серию «The IT Crowd» (с английского языка «Айтишники»)- это про тебя?
-2
20 ГБ для STM32, Atmel, PIC?
20Гб — это под iOS.
Нет, это реально здоровый проект, и можно позволить хранить его на локальном сервачке.
Но, например, есть у меня проектец под stm32f429 с размером рабочей папочки over 2 Гб. И что?

И это хранить в потенциально санкционно-забаненном Облаке?
Ну не хочется — можно не хранить. Просто это удобно.
На руках все равно всегда есть весь репозиторий локально — облако для синхронизации. Не хочется облако — можно поднять локальный сервачок с ssh и слабеньким raid'ом, да поднять на ней VCS, какую понравится.
Но надо ли?

Реально только самострелы так делают :)
Вам нравится слово «самострел»?))) Дык вы гляньте в википедию (это такая как будто БСЭ, только не на бумаге, а в Интернете), хоть посмотрите, что оно значит) А то выглядите глуповато)

я не знаю, что такое «информационные технологии» и что такое «гуру».
Дык с этого и стоило начинать) Вы рецензии на сериалы пишите?
+2
И это хранить в потенциально санкционно-забаненном Облаке?
Реально только самострелы так делают :)

Вы явно спорите о вещах, в которых не разбираетесь и о которых знаете понаслышке.

Ваш вариант хранение срезов версий кода в архивах (через это прошил многие) это лучше, чем ничего. Только это не удобно. Современные VCS имеют на порядок больше возможностей и делается там все, в большинстве случаев, парой кликов мышкой не покидая IDE (если Вам так не нравиться интерфейс командной строки – есть куча GUI оболочек, есть плагины или наивная поддержка для разных IDE)

Даже если Вы работаете над проектом один – VCS очень сильно облегчает работу. Если говорить о командной работе с кодом – там без VCS вообще делать нечего.
+2
Смотрел IT Crowds.
Делал архивы как у вас. Только с созданием их одной кнопкой с добавлением даты в имени файла.
Суммарный размер насчитывал гигабайты.
Перешли на SVN (гадость), потом на Git. В итоге размер в 30 МБ всего лишь, притом что в истории хранится (после смены SVN на Git) каждый чих, каждая изменённая строчка, которую (изменение) можно найти, если она вызвала проблему.
Данные храню в потенциально санкционно-забаненном Облаке GitHub, на домашнем сервере, в папке на флэшке, в папке на рабочем ПК и в папке на сервере компании. Пусть вводят санкции в облаке, пофиг :)
То что вы делаете — глупость. Причём не столько потому, что делаете архивы (все через это проходили поначалу), а потому что отказываетесь от гораздо более удобного средства под какими-то глупыми причинами самоубеждения (не знаю и знать нехочу).
+2
Например, сейчас папка проекта, над которым я работаю с командой на работе занимает около 20Гб.
А у меня все равно длиннее! Кто ещё желает ***** померятся? Кончайте детский сад разводить.
0
Но, например, есть у меня проектец под stm32f429 с размером рабочей папочки over 2 Гб. И что?
Это похоже на выяснение у кого толще?)
Нет, я писал это для того, чтобы показать, что 60Мб embed-проект нынче не назовешь уж сильно большим.
+1
А если вас попросят написать проект с поддержкой процессоров STM32, Atmel, PIC, и еще парочки других, при этом для каждой платформы в процессе работы рождается ветка 1, 2 и 3, которые начинают по тихой независимо друг от друга развиваться, при этом используя общую часть бизнес-логики.
У меня была подобная ситуация. Написал я проект, через некоторое время меня попросили сделать вариант «с кнопочкой». Я скопировал проект, сделал изменения в коде и назвал его «Проект с кнопочкой». Позже выяснилось, что лучше немного изменить алгоритм работы устройства. Изменил. Потом полез менять в «Проекте с кнопочкой». Через N-ное количества раз мне это надоело, и я начал использовать препроцессорные инструкции #ifdef для сборки прошивки «с кнопочкой» и «без». Вот теперь присматриваюсь к системам контроля версий с хранением в облаке (Git). Вот так, как говорят, не доходит через голову — дойдер через руки :))))
+1
Тоже так делал — потом перешел на git. Мне оказалось удобнее на bitbucket хранить, чем локально.
0
Вот пример ввода объекта в работу и последующее сопровождение и добавление функциональности по просьбе Заказчика
О, эта картинка — лучшая иллюстрация того, почему VCS нужен даже при разработке в одиночку.
Ну и из мелочей — в VCS архивчик версии, где изменена пара строк не будет весить 50МБ. Так что репозиторий с полной историей такого проекта будет весить не гиг, а мегабайт 50-100.
// Store i to m_Состояние_Привода
m_Drive_Status = i; // Это ТУПАЯ ОПЕРАЦИЯ для запутывания Заказчика
Ни одного полезного комментария в этом куске кода нет.
+1
Вы руками делаете то, что должен делать компьютер. Ваш выбор, но это конечно указывает на отсутствие нормального опыта работы не в одиночку.
+1
А месье знает толк… Читал пост и не покидало меня непонятное чувство, а потом дошло — в реальности, Asa Akira это один человек ;)
0
Так точно)
Всем лучей добра в это чЯте))
0
Автору респектище!
+2
Раз автор разбирается в гит, побеспокою и я своим нубским вопросом. Короче, пытаюсь добавить драйвер в embedded linux, но при установке:
~# insmod gpio-altera.ko
gpio_altera: version magic '3.13.0 SMP mod_unload ARMv7 p2v8 '
 should be '3.12.0-00307-g507abb4-dirty SMP mod_unload ARMv7 p2v8 '

Короче думаю понятно, не совпадают версии ядра. После гуглинга, понял что надо выкачать с гита нужную версию ядра(ниже магическая строчка как это сделать) и скомпилировать драйвер с ним:
#!/bin/bash -ex
git clone http://git.rocketboards.org/linux-socfpga.git
pushd linux-socfpga && git checkout -t -b socfpga-3.12.0 origin/socfpga-3.12.0 && popd

Вообщем с n попытки наконец получилось сделать, но:

insmod fpga_uinput.ko
fpga_uinput: version magic '3.12.0-00324-g28301d2 SMP mod_unload ARMv7 p2v8 '
 should be '3.12.0-00307-g507abb4-dirty SMP mod_unload ARMv7 p2v8 '

Короче я, то понимаю что проблема в несовпадении записей после 3.12.0(надо -00307-g507abb4-dirty), но блин при добавлении этих данных в комманду push выдает ошибку, и как выкачать нужную версию я не знаю :-(((((
0
Вооон тот кекс в номере версии сильно смахивает на номер ревизии. Попробуй git checkout g507abb4.
0
git clone git.rocketboards.org/linux-socfpga.git
pushd linux-socfpga && git checkout -t -b socfpga-3.12.0 origin/socfpga-3.12.0 && popd
Выглядит так:
1. Сначала клонируется удаленный репозиторий в папку linux-socfpga
2. Заходим в папку linux-socfpga, сохранив при этом путь, в котором мы были
3. Создаем локальную ветку socfpga-3.12.0, которая будет следить за удаленной веткой origin/socfpga-3.12.0
4. Возвращаемся в папку, в которой мы были перед тем как зашли в linux-socfpga

Вероятно с момента, когда писали этот ответ, HEAD этой ветки ушел, и теперь показывает не на ту подверсию.
Было бы неплохо найти откуда в логе берется строка (из каких компонент формируется, если формируется)
'3.12.0-00324-g28301d2 SMP mod_unload ARMv7 p2v8 '

И найти коммит, в котором эта строка (или компоненты) соответствуют
'3.12.0-00307-g507abb4-dirty SMP mod_unload ARMv7 p2v8 '


g507abb4 и g28301d2 — похоже на короткие хэшики коммитов, но в них 8 символов, а в коротких хэшах вроде 7.
0
Спасибо за развернутый ответ. Я только разбираюсь с линуксом и многое приходиться постигать методом научного тыка.
Строка (с номером версии) это ответ ядра на попытку скормить ему драйвер. Сначала оно матюкнулось мол чё ты мне 3.13 версию суешь. Я нашел ссылку ( те команды для гит, что я привел) для версии 3.13 и просто подставил 3.12.
Но увы не получилось, попробую по совету VGA скачать по тел коду, может что и получится.
0
Долбаная автоподстановка, нет тел код, а хеш код.
0
но в них 8 символов, а в коротких хэшах вроде 7
Мне помнится, что гит понимает сокращенные хэши любой длины, лишь бы они были уникальны.
0
Любителям крышечек: HEAD^^^^^ эквивалентно HEAD^5!!!
0
хлопнуть ветку asa до одного коммита с помощью команды git rebase -i
Зачем??? Есть же git merge --no-ff
Один аккуратный коммит в мастере, и полная история его появления в отдельной ветви.
+1
  • avatar
  • rius
  • 09 февраля 2015, 09:29
Просто хотел рассказать про rebase -i)
0
Как все описанное в этих 2-х статьях можно применить к программированию МК? Наделать кучу веток «SPI», «RS232», «LED» и т.п. и потом их «объединять»? Производительность труда упадет в разы по сравнению с простым поиском в папке и применением команды include.

ЗЫ Сам сталкивался не раз с разными версиями одного и того же проекта на флешке, домашнем и рабочим компьютером. Но все равно, хоть убейте, не понимаю зачем весь этот гемор на счет «контроля версий».
0
В простейшем применении даже веток делать не надо. Просто пишите логически законченный блок — коммит — пишите — коммит и так далее. Всего один хоткей в IDE, всё равно, что сохраниться.
НО
Вдруг захотелось "… а дайка я попробую вот-так..."


И тут понеслось: хочется и старое не сломать, и новое попробовать. Проще элементарно переключиться на ветку, и творить что угодно, потом либо слить, либо отбросить её.
Или посмотреть, «а что там было в той функции до того, как я её переписал?» Можно просто промотать по истории и глянуть. Даже как подсказку.
0
Штука может и хорошая, но это ведь переключение между средой разработки и менеджером проектов (или как его назвать). Постоянно отвлекаться чтобы на кнопочку заливки нажать. Можно, конечно, попробовать — давно думаю об этом.
0
В среду функционал VCS уже встроен. Во всяком случая в уважающую себя среду.
0
Например, куда? И где его найти, в каких настройках?
0
Какая IDE?
0
С++builder6 и avrstudio, например
0
Не пользовал, не знаю. Камрады подскажут.
0
А что пользовал? В какие ide встроено?
0
Под МК — эклипс, но давно уже не писал ничего. По работе — Qt, соответственно Qt Creator
0
О, у меня тоже есть этот Qt Creator. Забросил, правда, его. Может быть вернуть надо :)
0
Через его интерфейс вы не оцените удобство git. Вангую что только хуже будет.
Лучше первые 3 главы книги Pro Git усвоить и попробовать примеры на практике.
+2
В Eclipse, Qt Creator. Но консоль намного удобнее. Проще ввести пару команд с автодополнением по Tab, чем бегать по менюшкам мышой.
+1
Кстати верно — я использую его только из консоли. Если боитесь её, то можно встроенными средствами.
0
В билдер ставится расширение среды (если есть под нужную VCS), она там весьма гибкая. Правда, я им не пользуюсь, предпочитая использовать TortoiseSVN из эксплорера.
В AS5+ подхватывается провайдер для MSVS, например AnkhSVN для SVN, для гита и ртути — не знаю.
В AS4 — ничего, разве что в меню Tools вписывать. Но с такой IDE и интеграция не нужна.
В Keil и MPLAB — из коробки (под некоторые системы, правда, придется вручную команды прописывать).
0
Для мк у меня открыт терминал с 3 вкладками — OpenOCD, Telnet к нему, git. Никуда отвлекаться не надо.
Изменили несколько строк в инициализации чего-нибудь — закоммитили. Исправили дергание ножкой — занесли именно эти строки (Hg позволяет такое?) в коммит, отдельно от исправленных в то же время UART и ADC. А потом и их тоже отдельно закоммитили.
При этом в истории видно, что именно было изменено и в дальнейшем поможет найти возможную ошибку. Или попробовать что-то сделать иначе с нужного места. Или отменить неудачную ветвь развития и пойти другим путём.
Переключение времени не занимает, профита гораздо больше, чем затрат времени.
+3
Да, это только читается громоздко и сложно, по времени — секунды.
Какие-то сложные действия могут потребоваться раз в жизни — можно и почитать. В случае файловых хранилищ это равносильно потере архивов.

Прелесть гита — хранится ВСЁ. То есть уничтожить данные можно только грохнув репозиторий. Даже если что-то сделал не так, всё можно восстановить, хоть и сложно.
+1
Выше plcist показал как раз то, для чего нужны VCS.
Времени на работу с ними уходит совершенно несущественное количество, куда меньше, чем на подобные архивы. Зато экспериментируешь смело и не боясь что-то сломать. Даже если сломаешь — реверт или дифф с предыдущей версией (если надо откатить только часть) спасет.
Ну и синхронизацию между несколькими рабочими копиями облегчает резко. Командуешь «апдейт» и не задумываешься ни о том, чтобы не потерять какие-то изменения, ни о чем — если даже чего, то VCS предупредит и поможет разрулить.
0
С++builder6 и avrstudio, например
0
А можно как-то сделать такое:
1. Файл содержит данные
2. в файл добавляются новые данные
3. файл редактируется удалением некоторых данных из п.1
Требуется получить файл из п.3, но без учета процедур добавленных на этапе 2. Действия по изменению последовательные.
0
git revert, но в зависимости от оформления кода может потребоваться ручная правка.
0
Спасибо. Отличный цикл статей для быстрого старта. Лично мне именно такого и не хватало, чтобы начать пользоваться GIT-ом. Только вы этот цикл не забрасывайте, продолжайте и дальше.
+1
Кстати, для быстрого знакомства с GIT есть неплохие интерактивные обучалки. Вот базовая, вот более продвинутая.
0
  • avatar
  • e_mc2
  • 15 февраля 2015, 20:52
Помнится мне, где-то еще был аналог hg init для гита. Только не помню где.
0
0
GitHowTo, да.
0
Для win есть замечательная вещь TortoiseGIT.
В неё уже встроена утилита для слияний и поглоще, которая может трехстороннее редактирование как на картинках делать. Пользуюсь уже пару лет и очень доволен наглядностью и полезностью утилиты.
0
  • avatar
  • ujin5
  • 16 февраля 2015, 15:50
Покажи окошко About этой утилитки.
0
0
Ага, из TortoiseSVN утилитка. Вообще, многие о ней хорошо отзываются, жаль с версии 1.6.7 отдельно от TSVN (и, видимо, Tgit) не выпускается…
Интересно, есть ли какие-то отличия от той версии, что в составе TSVN.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.