Многопоточность – не сложно
Как мне кажется, наиболее оптимальной стратегией при написании многопоточного кода является перенос работы с разными потоками на как можно более высокий уровень абстракции. Отдельные функции должны писаться в “чистой” парадигме, а ответственность за параллельные изменения должна быть в едином месте, примерно рядом с созданием этих потоков.
Самой большой проблемой в многопоточке является доступ к единой переменной, и чем сильнее раскидано обращение к этой переменной по классу, тем менее читаемый и масштабируемый код мы получаем в итоге. Старайтесь как можно реже изменять общие мутабельные объекты в разных функциях класса – прокидывайте их через аргументы и возвращайте измененные как результат функции.
При написании целого класса проверьте, что все публичные методы готовы к вызовам на разных потоках извне – потребитель класса не должен задумываться о том, как правильно с ним работать, если явно не указано иное.
Ниже два почти одинаковых класса, которые выдают один и тот же результат в однопоточной среде. Оба класса можно сделать потокобезопасными, но в первом случае придется учитывать все методы, а во втором – только метод
Пример дурацкий, но надеюсь, удалось передать основную мысль.
И да, это не решение на все случаи жизни, но позволяет быстро реализовывать большое кол-во простых задач на многопоточность.
#программирование #многопоточность
Как мне кажется, наиболее оптимальной стратегией при написании многопоточного кода является перенос работы с разными потоками на как можно более высокий уровень абстракции. Отдельные функции должны писаться в “чистой” парадигме, а ответственность за параллельные изменения должна быть в едином месте, примерно рядом с созданием этих потоков.
Самой большой проблемой в многопоточке является доступ к единой переменной, и чем сильнее раскидано обращение к этой переменной по классу, тем менее читаемый и масштабируемый код мы получаем в итоге. Старайтесь как можно реже изменять общие мутабельные объекты в разных функциях класса – прокидывайте их через аргументы и возвращайте измененные как результат функции.
При написании целого класса проверьте, что все публичные методы готовы к вызовам на разных потоках извне – потребитель класса не должен задумываться о том, как правильно с ним работать, если явно не указано иное.
Ниже два почти одинаковых класса, которые выдают один и тот же результат в однопоточной среде. Оба класса можно сделать потокобезопасными, но в первом случае придется учитывать все методы, а во втором – только метод
changeNumber. В случае масштабирования или изменения первого класса когнитивная нагрузка значительно вырастает – общий скоуп работ начинает затрагивать огромное кол-во мест. Во втором классе вне зависимости от масштабов думать придется опять же только над методом changeNumber.
class SomeBadService {
private var number: Int = 0
fun changeNumber(): Int {
change1()
change2()
change3()
return number
}
private fun change1() {
number++
}
private fun change2() {
number--
}
private fun change3() {
number += 2
}
}
class SomeBetterService {
private var number: Int = 0
fun changeNumber(): Int {
val firstChange = change1(number)
val secondChange = change2(firstChange)
val thirdChange = change3(secondChange)
number = thirdChange
return number
}
private fun change1(num: Int): Int {
return num + 1
}
private fun change2(num: Int): Int {
return num - 1
}
private fun change3(num: Int): Int {
return num + 2
}
}
Пример дурацкий, но надеюсь, удалось передать основную мысль.
И да, это не решение на все случаи жизни, но позволяет быстро реализовывать большое кол-во простых задач на многопоточность.
#программирование #многопоточность
❤3👍2
Перестаём душнить на code review
Подключили на проекте Danger.
Эта утилита позволяет автоматизировать проверку кода на CI через написание скриптов. Теперь душнить вместо вас будет бот.
В рамках скрипт-файла вам предоставляется доступ к сущности git, откуда вы можете достать такую информацию, как профиль автора, название PR, коммиты, диффы отдельных файлов и т.д.
Оригинальный Danger понимает Ruby-синтаксис, но есть отдельная версия под JS. Если вы хотите писать скрипт на другом языке, то нужно проверять наличие утилиты на официальном сайте,но это уже костыльные обёртки над оригиналами и часть функционала может отсутствовать.
Как подключить?
1. Создаёте access token на git-платформе.
2. Создаёте ci-таску из докер-образа на основе нужной вам утилиты (в моём случае это danger-kotlin).
3. Прописываете в переменную окружения таски access token.
4. Создаёте скрипт-файл по инструкции вашей утилиты.
5. Делаете PR. По итогу выполнения таски бот сам напишет комментарии в соответствии с вашим скриптом.
Утилита поддерживает плагины. Есть куча готовых по интеграции с линтерами, детектами и прочим, но также можно писать свои.
Мы в проекте подключили такие проверки:
1. Проверка названия и описания MR.
2. Если к модулю app был подключён дочерний модуль, то проверяем наличие тестов в дочернем.
3. Если были изменения строк, связанных с классами отправки аналитики, то просим провести регресс аналитики конкретных модулей.
Подключили на проекте Danger.
Эта утилита позволяет автоматизировать проверку кода на CI через написание скриптов. Теперь душнить вместо вас будет бот.
В рамках скрипт-файла вам предоставляется доступ к сущности git, откуда вы можете достать такую информацию, как профиль автора, название PR, коммиты, диффы отдельных файлов и т.д.
Оригинальный Danger понимает Ruby-синтаксис, но есть отдельная версия под JS. Если вы хотите писать скрипт на другом языке, то нужно проверять наличие утилиты на официальном сайте,
Как подключить?
1. Создаёте access token на git-платформе.
2. Создаёте ci-таску из докер-образа на основе нужной вам утилиты (в моём случае это danger-kotlin).
3. Прописываете в переменную окружения таски access token.
4. Создаёте скрипт-файл по инструкции вашей утилиты.
5. Делаете PR. По итогу выполнения таски бот сам напишет комментарии в соответствии с вашим скриптом.
Утилита поддерживает плагины. Есть куча готовых по интеграции с линтерами, детектами и прочим, но также можно писать свои.
Мы в проекте подключили такие проверки:
1. Проверка названия и описания MR.
2. Если к модулю app был подключён дочерний модуль, то проверяем наличие тестов в дочернем.
3. Если были изменения строк, связанных с классами отправки аналитики, то просим провести регресс аналитики конкретных модулей.
danger.systems
Danger JS
Apply cultural rules during your CI process.
👍2
Просто оставлю это здесь. Особенно нравится картинка с пирамидками, чем-то напонимает принцип Парето.
Иногда при старте проекта тяжело определить границы MVP, помогает насмотренность и мысленные упражнения. Например, можно взять популярный продукт и срезать с него все лишнее – что у вас получится? Стали бы вы пользоваться таким продуктом?
Иногда при старте проекта тяжело определить границы MVP, помогает насмотренность и мысленные упражнения. Например, можно взять популярный продукт и срезать с него все лишнее – что у вас получится? Стали бы вы пользоваться таким продуктом?
👍2✍1
На Хабре вышла статья под моим авторством, буду рад вашим визитам
https://habr.com/ru/companies/wildberries/articles/905238/
#habr #android
https://habr.com/ru/companies/wildberries/articles/905238/
#habr #android
Хабр
Типобезопасная передача результатов между экранами в Compose с Jetpack Navigation
Приветствую Android-комьюнити! Меня зовут Арсений Шпилевой, я Core-разработчик в команде WB Partners. В этой небольшой статье я расскажу, как мы в проекте решили обеспечить типобезопасность при...
🔥1🎉1👀1
Forwarded from WBTECH
Android Meetup всё ближе: делимся программой вечера 📆
➡️ «Виджеты на Android: это просто?»
Александр Гирев, Android Team Lead продуктовой команды WB Partners
Расскажем, как и почему виджет приложения живёт в другом процессе, разберёмся, как устроено обновление виджетов и применение Live Updates, посмотрим, можно ли отрисовать на виджете розового пони 😅
➡️ «Compose+Koin+JetpackNavigation: что мы поняли за 2 года»
Арсений Шпилевой, Android-разработчик core-команды WB Partners
Расскажем, к какой архитектуре мы пришли за два года существования проекта, как мы укротили навигацию от Google и всё это подружили с Koin.
➡️ «Интеграция Android-приложений: подходы и лучшие практики»
Абакар Магомедов, главный техлид разработки в Альфа-Банке
Рассмотрим случай, когда необходима интеграция двух мобильных приложений, разберёмся, как решить задачу интеграции при помощи Server Driven UI и с какими проблемами можно столкнуться при выносе общей фичи в отдельную библиотеку.
Когда:
4 июля с 17:00 начинается сбор гостей, 18:15 стартует митап. Приходите заранее, чтобы выдохнуть, перекусить, настроиться на доклады.
Где:
Москва, пространство Весна
Не сможете прийти? Заходите на онлайн-трансляцию (ссылки будут позже в канале)
Регистрация уже открыта — до встречи!
#wbtech #wbmeetups #wbspeakers #wbandroid
Александр Гирев, Android Team Lead продуктовой команды WB Partners
Расскажем, как и почему виджет приложения живёт в другом процессе, разберёмся, как устроено обновление виджетов и применение Live Updates, посмотрим, можно ли отрисовать на виджете розового пони 😅
Арсений Шпилевой, Android-разработчик core-команды WB Partners
Расскажем, к какой архитектуре мы пришли за два года существования проекта, как мы укротили навигацию от Google и всё это подружили с Koin.
Абакар Магомедов, главный техлид разработки в Альфа-Банке
Рассмотрим случай, когда необходима интеграция двух мобильных приложений, разберёмся, как решить задачу интеграции при помощи Server Driven UI и с какими проблемами можно столкнуться при выносе общей фичи в отдельную библиотеку.
Когда:
4 июля с 17:00 начинается сбор гостей, 18:15 стартует митап. Приходите заранее, чтобы выдохнуть, перекусить, настроиться на доклады.
Где:
Москва, пространство Весна
Не сможете прийти? Заходите на онлайн-трансляцию (ссылки будут позже в канале)
Регистрация уже открыта — до встречи!
#wbtech #wbmeetups #wbspeakers #wbandroid
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1🔥1🎉1🏆1
На днях попробовал сделать аналог стекломорфизма из iOS 26 для Android Compose.
Мои попытки вылились в небольшую библиотеку, которая добавляет настраиваемый стеклянный контейнер для вьюшек.
Подробнее можно посмотреть в репозитории https://github.com/Mortd3kay/liquid-glass-compose
Из интересного в разработке:
0. Compose не умеет вычитывать пиксели не из дочерних вьюх – пришлось идти на ухищрение и оборачивать всю конструкцию в контейнер.
1. Стекло хотелось сделать настраиваемым – референсы брал с этих проектов раз два три.
2. Настраиваемость стекла сильно ограничивает в использовании displacement-карт, поэтому решил преломлять цвет алгоритмически.
3. Моделировать реальную линзу неэффективно и не нужно, поэтому была разработана хитрая имитация – здесь очень помогал Cursor.
4. Отражение соседних элементов требовало написания RayMarching'а – как по мне, это дорого, поэтому для блика стекла просто берется цвет пикселей на небольшом расстоянии от границы.
Мои попытки вылились в небольшую библиотеку, которая добавляет настраиваемый стеклянный контейнер для вьюшек.
Подробнее можно посмотреть в репозитории https://github.com/Mortd3kay/liquid-glass-compose
Из интересного в разработке:
0. Compose не умеет вычитывать пиксели не из дочерних вьюх – пришлось идти на ухищрение и оборачивать всю конструкцию в контейнер.
1. Стекло хотелось сделать настраиваемым – референсы брал с этих проектов раз два три.
2. Настраиваемость стекла сильно ограничивает в использовании displacement-карт, поэтому решил преломлять цвет алгоритмически.
3. Моделировать реальную линзу неэффективно и не нужно, поэтому была разработана хитрая имитация – здесь очень помогал Cursor.
4. Отражение соседних элементов требовало написания RayMarching'а – как по мне, это дорого, поэтому для блика стекла просто берется цвет пикселей на небольшом расстоянии от границы.
🔥6🆒2❤1🤯1🥱1
Месяц назад я решил принять участие в контесте Telegram – нужно было переработать экран профиля, добавив кнопки и анимацию подарков, как это сделано на iOS.
Сегодня объявили результаты и я вошел в число тех, кто занял 2 место – очень приятно, учитывая, что это мой первый опыт в подобных соревнованиях. Не успел осилить размытие под кнопками и эффект прилипания аватарки при сворачивании, но все равно вышло неплохо. Даже порефачил немного код:)
Ниже представлен результат моей работы:
Сегодня объявили результаты и я вошел в число тех, кто занял 2 место – очень приятно, учитывая, что это мой первый опыт в подобных соревнованиях. Не успел осилить размытие под кнопками и эффект прилипания аватарки при сворачивании, но все равно вышло неплохо. Даже порефачил немного код:)
Ниже представлен результат моей работы:
Media is too big
VIEW IN TELEGRAM
🏆15🥴4🎉3💅3❤2⚡1🤷♀1🔥1
Недавно решил сделать свое первое расширение для браузера. На пробу взял простую идею – уведомлять пользователя, если он просматривает экстремистский контент или сайт (актуально в связи с последними поправками).
В качестве источника данных решил использовать официальный сайт Минюста РФ. Написал простенький парсер, который вытягивает все ссылки из материалов. Также добавил поиск по совпадению метаданных страницы с цитатами.
Алгоритм пока работает очень просто и часто может ругаться на простые запросы – для этого добавил возможность прятать такие запросы в белый список.
Расширение можно поставить через Chrome Web Store https://chromewebstore.google.com/detail/%D1%80%D0%B5%D0%B5%D1%81%D1%82%D1%80-%D1%8D%D0%BA%D1%81%D1%82%D1%80%D0%B5%D0%BC%D0%B8%D1%81%D1%82%D1%81%D0%BA%D0%B8%D1%85-%D0%BC%D0%B0%D1%82/hekgklmbcplgagdemhopbpfkecaphade?hl=en-US
В качестве источника данных решил использовать официальный сайт Минюста РФ. Написал простенький парсер, который вытягивает все ссылки из материалов. Также добавил поиск по совпадению метаданных страницы с цитатами.
Алгоритм пока работает очень просто и часто может ругаться на простые запросы – для этого добавил возможность прятать такие запросы в белый список.
Расширение можно поставить через Chrome Web Store https://chromewebstore.google.com/detail/%D1%80%D0%B5%D0%B5%D1%81%D1%82%D1%80-%D1%8D%D0%BA%D1%81%D1%82%D1%80%D0%B5%D0%BC%D0%B8%D1%81%D1%82%D1%81%D0%BA%D0%B8%D1%85-%D0%BC%D0%B0%D1%82/hekgklmbcplgagdemhopbpfkecaphade?hl=en-US
🔥2👀2❤1⚡1👍1🦄1
По мотивам доклада с митапа подготовили новую статью на Хабре.
https://habr.com/ru/companies/wildberries/articles/939526/
#habr #android
https://habr.com/ru/companies/wildberries/articles/939526/
#habr #android
Хабр
Compose + Koin + Jetpack Navigation: что мы поняли за 2 года
Привет, Хабр! Меня зовут Арсений Шпилевой, и я Android-разработчик в core-команде WB Partners Wildberries & Russ. Сегодня поделюсь нашим опытом развития архитектуры приложения на Jetpack Compose:...
🔥7✍1👀1
This media is not supported in your browser
VIEW IN TELEGRAM
🚀 Agent2Models: Один промпт – несколько ИИ-моделей под капотом
Столкнулся с тем, что для сложных задач приходится вручную собирать пазл из разных моделей: одна генерирует код, другая проверяет логику, третья оптимизирует текст. Но переключаться между ними – муторно, а готовые решения либо слишком жестко привязаны к платформам, либо требуют постоянного контроля.
Написал небольшой сервис, который поможет решить эту проблему.
Что внутри:
🔹 Гибкая маршрутизация: Отправляйте разные части задачи в профильные модели (например, математику — в Claude, креатив – в Gemini) с помощью одного промпта
🔹 Автоматическое сравнение: Агент сам обратится к моделям, обработает их результаты и выдаст наилучший ответ
🔹 Простая интеграция: Работает через MCP – подключите за 5 минут без костылей.
Проект переходит в стадию Беты:
✨ Никаких платежных карт
✨ Только один тариф – полный доступ
✨ Ваш фидбек напрямую повлияет на дорожную карту.
Приглашаю к тестированию:
Если ваш агент работает с MCP –попробуйте. Нашли баг или есть идея для улучшения? На сайте есть форма обратной связи.
P.S. Уже есть идеи для V2. Но сначала – ваше мнение. 💡
📱 https://ai-mcp.app
#AI #beta #MCP
Столкнулся с тем, что для сложных задач приходится вручную собирать пазл из разных моделей: одна генерирует код, другая проверяет логику, третья оптимизирует текст. Но переключаться между ними – муторно, а готовые решения либо слишком жестко привязаны к платформам, либо требуют постоянного контроля.
Написал небольшой сервис, который поможет решить эту проблему.
Что внутри:
🔹 Гибкая маршрутизация: Отправляйте разные части задачи в профильные модели (например, математику — в Claude, креатив – в Gemini) с помощью одного промпта
🔹 Автоматическое сравнение: Агент сам обратится к моделям, обработает их результаты и выдаст наилучший ответ
🔹 Простая интеграция: Работает через MCP – подключите за 5 минут без костылей.
Проект переходит в стадию Беты:
✨ Никаких платежных карт
✨ Только один тариф – полный доступ
✨ Ваш фидбек напрямую повлияет на дорожную карту.
Приглашаю к тестированию:
Если ваш агент работает с MCP –попробуйте. Нашли баг или есть идея для улучшения? На сайте есть форма обратной связи.
P.S. Уже есть идеи для V2. Но сначала – ваше мнение. 💡
#AI #beta #MCP
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4🤯3🏆1
Как ИИ может убить ваш проект (и что из этого можно вынести)
Когда пишешь пет-проект, хочется сфокусироваться на продукте, а не на инфраструктуре. Так и я решил отдать ИИ задачу сгенерировать docker-compose.yml. Ниже представлен небольшой кусок этого конфига:
На первый взгляд ничего такого – поднимаем контейнер с редисом на 6379 порту, делаем healthcheck по таймауту. Всё заработало с первого раза: контейнер поднялся, приложение общалось с Redis, я задеплоил это на прод-сервер и забыл.
Через пару месяцев захотел подключить админку к Redis… и обнаружил неприятную вещь: подключиться можно без пароля и даже без SSH. Redis был доступен напрямую из интернета на стандартном порту 6379.
Проверил логи – и увидел регулярные (раз в несколько дней) атаки:
- Создание
- Попытки записать SSH-ключи через
- Последующая очистка логов через
К счастью, Redis использовался только как очередь (Celery), данные не критичны, и утечки не произошло. Но это могло закончиться иначе.
Я также проверил основную БД (PostgreSQL) – у неё тоже был открыт порт, но там я вручную прописал нестандартное имя пользователя и сложный пароль. Даже так – в логах были попытки брутфорса под
Кто это делал?
Не целевые хакеры – просто боты, сканирующие весь IPv4-пространство в поиске открытых Redis, MongoDB, PostgreSQL и т.д. Они работают 24/7. Если ваш сервис публично доступен – он уже в их прицеле.
Что делать?
- Не используйте
- Всегда включайте аутентификацию: даже в Redis можно задать
- Никогда не доверяйте «готовым» конфигам от ИИ без аудита – особенно в инфраструктуре.
- Если ваш проект доступен из интернета – считайте, что он атакуется сразу после деплоя.
Безопасность – не опция. Особенно когда ИИ делает всё «за вас».
#AI #Docker #Redis
Когда пишешь пет-проект, хочется сфокусироваться на продукте, а не на инфраструктуре. Так и я решил отдать ИИ задачу сгенерировать docker-compose.yml. Ниже представлен небольшой кусок этого конфига:
redis:
image: redis:7-alpine
container_name: redis
ports:
- "6379:6379"
restart: unless-stopped
networks:
- app-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
На первый взгляд ничего такого – поднимаем контейнер с редисом на 6379 порту, делаем healthcheck по таймауту. Всё заработало с первого раза: контейнер поднялся, приложение общалось с Redis, я задеплоил это на прод-сервер и забыл.
Через пару месяцев захотел подключить админку к Redis… и обнаружил неприятную вещь: подключиться можно без пароля и даже без SSH. Redis был доступен напрямую из интернета на стандартном порту 6379.
Проверил логи – и увидел регулярные (раз в несколько дней) атаки:
- Создание
REPLICAOF на внешний сервер,- Попытки записать SSH-ключи через
CONFIG SET dir и CONFIG SET dbfilename,- Последующая очистка логов через
FLUSHALL.К счастью, Redis использовался только как очередь (Celery), данные не критичны, и утечки не произошло. Но это могло закончиться иначе.
Я также проверил основную БД (PostgreSQL) – у неё тоже был открыт порт, но там я вручную прописал нестандартное имя пользователя и сложный пароль. Даже так – в логах были попытки брутфорса под
root, admin, test и т.п.Кто это делал?
Не целевые хакеры – просто боты, сканирующие весь IPv4-пространство в поиске открытых Redis, MongoDB, PostgreSQL и т.д. Они работают 24/7. Если ваш сервис публично доступен – он уже в их прицеле.
Что делать?
- Не используйте
ports в docker-compose, если сервис не должен быть доступен извне. Внутри сети Docker достаточно expose (или вообще ничего – по умолчанию контейнеры в одной сети видят друг друга).- Всегда включайте аутентификацию: даже в Redis можно задать
requirepass через переменную окружения или конфиг.- Никогда не доверяйте «готовым» конфигам от ИИ без аудита – особенно в инфраструктуре.
- Если ваш проект доступен из интернета – считайте, что он атакуется сразу после деплоя.
Безопасность – не опция. Особенно когда ИИ делает всё «за вас».
#AI #Docker #Redis
👍5❤2🔥2👾1
Как не терять время при переключении веток?
Многие системы сборки предполагают кэширование результатов, чтобы ускорять последующие сборки. Но когда параллельно работаешь над несколькими задачами, этот кэш приходится пересобирать при каждой смене ветки.
Для решения этой проблемы можно сделать копии репозиториев, и в каждой работать над отдельной задачей. Вы можете подумать, что этот подход противоречит идее VCS, но сам Git предоставляет такой механизм – называется он Git Worktree.
Как работает:
Командой
Чем это лучше обычной инициализации репозитория в другой папке:
1. Все рабочие деревья находятся в одном пространстве –
2. Не требуется заново настраивать конфиг гита, если он у вас кастомный для проекта.
3. Создание и удаление копии присходит одной командой из любого дерева.
Какие есть ограничения:
1. Нельзя в двух деревьях переключиться на одну ветку. Сделано для поддержания консистентности, достаточно просто отводить ветки и делать изменения в них.
2. Если в вашем проекте есть завязка на .git директорию (например, работа с хуками из .git/hooks), то эта функциональность может сломаться, потому что во всех деревьях .git – это ссылка на директорию в оригиналом проекте. Для обхода этой проблемы можно закомментировать ломающий функционал и скрыть изменение из индекса комадной
#git #worktree
Многие системы сборки предполагают кэширование результатов, чтобы ускорять последующие сборки. Но когда параллельно работаешь над несколькими задачами, этот кэш приходится пересобирать при каждой смене ветки.
Для решения этой проблемы можно сделать копии репозиториев, и в каждой работать над отдельной задачей. Вы можете подумать, что этот подход противоречит идее VCS, но сам Git предоставляет такой механизм – называется он Git Worktree.
Как работает:
Командой
git add worktree ../feature-branch-project main вы создаете проект по соседству с вашим. Если не указывать название ветки, то она принимает название директории (feature-branch-project) и ответвляется от ветки, указанной в конце (main). Поработав с веткой, мы можем вызвать команду git worktree remove ../feature-branch-project для удаления копии.Чем это лучше обычной инициализации репозитория в другой папке:
1. Все рабочие деревья находятся в одном пространстве –
fetch актуализирует информацию везде, новые ветки видны всем, есть возможность сделать rebase по ветке, которая находится в другом дереве. 2. Не требуется заново настраивать конфиг гита, если он у вас кастомный для проекта.
3. Создание и удаление копии присходит одной командой из любого дерева.
Какие есть ограничения:
1. Нельзя в двух деревьях переключиться на одну ветку. Сделано для поддержания консистентности, достаточно просто отводить ветки и делать изменения в них.
2. Если в вашем проекте есть завязка на .git директорию (например, работа с хуками из .git/hooks), то эта функциональность может сломаться, потому что во всех деревьях .git – это ссылка на директорию в оригиналом проекте. Для обхода этой проблемы можно закомментировать ломающий функционал и скрыть изменение из индекса комадной
git update-index --skip-worktree changed_file, тогда изменение не попадет в коммит, даже если сделаем git add -A.#git #worktree
❤3🤔3🥴1👀1