Найкращі звички контролю версій для соло-розробника?


36

Я єдиний розробник у своїй роботі, і хоча я розумію переваги VCS; Мені важко дотримуватися належних практик. Наразі я використовую git для розробки в основному веб-додатків (які ніколи не будуть відкриті через мою роботу).

Мій поточний робочий процес - це зробити багато змін на веб-сайті для розробки, перевірити, переглянути, протестувати, бути задоволеним та вчинити зміни, а потім підштовхнути посилання на активний сайт (тому якщо я працюю над великою новою зміною; я можу лише здійснювати один раз на тиждень, але мій IDE має гарну історію скасування неподілених матеріалів).

В основному, я використовую git лише для перемикання між машинами (наприклад, робочим комп'ютером Dev на домашній комп'ютер розробників чи на живій машині), але протягом дня я не бачу користі. Це призводить до того, що у мене є довгі списки змін (і у мене виникають проблеми з пошуком хорошого msg для кожної фіксації; і коли я поспішаю - я, як правило, залишаю хитрі повідомлення типу "зміни різного роду для адміністратора та шаблонів").

Як часто я повинен здійснювати вчинки? Чи повинна кожна зміна одного рядка взяти на себе зобов’язання? Чи потрібно зробити я перед будь-яким тестом (наприклад, принаймні для синтаксису / компіляції помилок, а потім доведеться повністю скасувати його, оскільки ідея не спрацювала або повідомлення є брехнею)?

Чи повинен я переконатися, що я виконую щоранку / вдень, перш ніж перестати працювати на вечерю, поки її ще свіже? Що мені не вистачає, маючи погані звички VCS?


2
Можливо, один із ваших зависань, чому ви вважаєте, що VCS не працює для вас, це тому, що ви використовуєте Git як соло-розробник? Git здається мені надмірним для одного розробника, можливо, щось простіше з меншими можливостями, як SVN, буде простіше у використанні?
maple_shaft

6
@maple_shaft: Я не використовував Git, але Mercurial настільки ж просто, як Subversion для основних сольних завдань розробника. (Простіше, насправді, оскільки створити еквівалент сховища простіше.)
Девід Торнлі

15
Чому git буде надмірним?
Тамас Шелей

1
@maple_shaft реальна користь настає пізніше. Не потрібно погоджуватися на менше.

3
Варто згадати, що для DVCS, таких як git і mercurial, щоб скористатися перевагами резервного резервного копіювання джерела керування джерелами (про що йдеться в деяких відповідях), вам потрібно буде регулярно просуватися, а не просто здійснювати.
буксири

Відповіді:


24

Вам багато чого не вистачає.

Я теж певним чином. Я щоразу вчиняю значну зміну або перед тим, як розпочати значну, щоб я міг повернутися назад, якщо я накручу щось, і то раз, то навіть якщо я не роблю нічого великого. Не щоденно насправді, але близько. Іноді кілька разів на день.

Що я отримую, це те, що я можу повернутися назад, коли захочу. Що багато. Також замовлення гілок допомагає.

Я думаю, це дає мені багато порядку.

Я використовую svn, і мені стає нудно. Але більше часу не можна витрачати на вивчення чого-небудь іншого.

Удачі.


+1 Я нещодавно сам почав використовувати VCS, і GIT - це для мене :)
yati sagade

1
Я довго уникав контролю над версіями, оскільки мав враження, що це занадто громіздко / некрасиво / дратує. Кілька місяців тому я вирішив ознайомитись із Subversion і тепер клянусь цим.
Dalin Seivewright

1
У мене є кілька сольних проектів: деякі на Github, інші ні. Я завжди використовую git, навіть якщо я просто будую щось для виразних цілей вивчення певного API / інструменту. Він застосовує добрі звички до реальних проектів, де це корисніше, як описує @jbcolmenares.
сарумон

2
Я протистояти вашому "не можу витрачати більше часу на вивчення чого-небудь іншого" з hginit.com . Порахуйте час, який ви витрачаєте сердитися на svn протягом одного тижня, а потім знайдіть таку кількість часу, щоб прочитати hginit наступного тижня.
тдаммери

@tdammers буде гляньте
Коші

18

Ви повинні робити зобов’язання часто. Вам, безумовно, слід скористатися після досягнення певної логічної віхи. Якщо це займає більше дня, вам слід принаймні взяти на себе зобов’язання наприкінці робочого дня, а ще краще - розбити свою роботу на менші шматки.

Є багато причин для цього. Наприклад, що робити, якщо ваш комп'ютер виходить з ладу? Набагато краще втратити роботу лише за день, ніж за тиждень чи місяць. Ще одна причина полягає в тому, що часті вчинки полегшують ізоляцію помилки. Ви можете виконати двійковий пошук і з’ясувати, які невеликі зміни спричинили помилку.

Інша річ: перед тим, як зробити зобов’язання, ви повинні зробити роздуми і переглянути всі внесені вами зміни. Це дозволяє перевірити, чи всі зміни мають сенс, і що ви нічого не забули. Це також допомагає вам придумати краще повідомлення про вчинення. І, звичайно, це ще одна причина, яку потрібно робити часто: набагато простіше пережити зміни, що добувають за день, ніж коштує місяць.


"що робити, якщо ваш комп'ютер виходить з ладу" - файли зберігаються на диску досить часто, а резервні копії робляться щоночі (якщо ви мали на увазі, якщо жорсткий диск зламається). Однак +1 для двійкового пошуку помилок може стати в нагоді. Я досить добре знаходжу 95% помилок; але раз у раз виникає по-справжньому химерна помилка, що виникає внаслідок, здавалося б, несуттєвої зміни в іншій частині програми.
dr jimbob

Так, я маю на увазі "якщо диск зламається", або "якщо стеля заглиблюється", або "якщо пристрій EMP знаходиться поблизу". :) Все, що може спричинити втрату даних. Часто доручення - це найпростіший спосіб створити резервну копію вашої роботи, і вона дозволяє легко робити резервну копію за межами сайту, використовуючи віддалений сервер управління версіями.
Діма

1
@Dima: Вам потрібно буде натиснути і не тільки взяти на себе зобов’язання мати резервну копію
liberforce

@liberforce Не всі системи управління версіями мають натискання. Ця відповідь - з 2012 року. Я в той час використовував підрив, який не поширювався. Отже, ніякого поштовху.
Діма

2
@Dima: впевнений, але ОП використовував git, тому інструкції можуть бути оманливими, оскільки ви не сказали, що говорили про SVN.
liberforce

10

Щоб отримати максимальну користь від CVS, вам слід працювати над однією функцією / виправленням помилок одночасно та здійснювати виконання, коли ця функція / виправлення помилок завершена. Цим ви отримаєте:

  • повідомлення про фіксацію буде простіше створити та матиме більше сенсу;
  • полегшене відстеження майбутніх помилок до змін, які їх внесли;
  • простіше повернути до попереднього стану (навіть якщо це означає втрату невдалої функції, але збереження виправлень помилок, які виникли згодом).

Крім того, оскільки ви переходите між ПК, у вас повинно бути принаймні дві гілки:

  • гілка "Ready to Go", яка завжди працює (за винятком помилок, над якими ви працюєте у галузі розвитку)
  • галузь розвитку, яка час від часу може перебувати у незбагненому стані (наприклад, під час поїздки додому з роботи;).

1
+1 для готової до відділення! Я не знаю, скільки разів мене просять показати програмне забезпечення, коли проходять шеф та потенційні клієнти. Приємно мати версію, яка насправді працює і не знаходиться в потоці.
синя накладна

Версія, яка працює і тестується, зазвичай позначена тегами. Це ви повинні показати, якщо тільки начальник не хоче побачити останні зміни. У такому випадку ви просто git stashі показуєте, що у вас є, або оформляєте певну комісію. Звичайно, якщо у вас великі зміни, які є незавершеною роботою, вони повинні бути в окремій галузі незавершеного виробництва, тому ваша головна галузь фактично є стабільною.
liberforce

7

Чи повинна кожна зміна одного рядка взяти на себе зобов’язання?

Якщо саме це виправляє помилку, обов'язково.

Що мені не вистачає, маючи погані звички VCS?

Я працював з хлопцем, який мав "погані звички VCS". Він любив працювати все сам і керував лінійкою продуктів, яка приносила щось на зразок 1 000 000 доларів США на рік. Він робив зобов’язання лише тоді, коли начальник наголосив на нього. Потім одного дня його жорсткий диск розбився. Після отримання заміни для нього ми виявили, що його останній заїзд був 6 місяців раніше. Оскільки VCS був безпечним для джерела, ви можете здогадатися, що ще пішло не так - остання комісія була пошкоджена. Нам довелося повернутися більше року, щоб отримати некорумповану версію його лінійки продуктів. Його не звільнили, хоча він і мав бути.

Ще один анекдот стосується самого мене. Раніше я зберігав код для хобі та дослідницьких проектів на знімних жорстких дисках. Одного разу в мене ввірвалася квартира. Був викрадений ноутбук (який був зламаний) та всі знімні жорсткі диски. Кожен DVD (за винятком Червоної зорі) був викрадений. Жоден із настільних комп'ютерів не вкрали. Якби я мав контроль над джерелами, я б не втрачав проектів на 15 років, тим більше, що деякі базувалися на академічних проектах - багато хто з професорів залишив академічні заклади, щоб перейти до приватної галузі, щоб ці проекти випали у чорну діру корпоративного ІС. втрачений код неможливо відновити.

Як часто я повинен здійснювати вчинки?

Я розбиваю її на кілька показників:

  • Скільки роботи ви готові втратити, якщо ваш комп’ютер помре? або викрадається?

  • Якщо це виправить Bug_1234, тоді перевірте код у коментарі "виправляє Bug_1234".

  • Якщо це логічний показ доставки / віху, тоді перевірте це у коментарі, наприклад "Bug_1234, form_xyz" (або Task_1234, якщо потрібно).

  • Завжди перевіряйте код у п'ятницю ввечері, перш ніж вирушати додому. Також зробіть реєстрацію (або скасуйте каси) усього, перш ніж вирушати у відпустку.

  • Кожен раз, коли диктує політика компанії.


1
Я згоден, хлопця слід було звільнити. Навіть не випуск, навіть принаймні для випусків - це божевілля. Як ви можете знайти помилок, які з'явилися у версії 1.2, якщо ви не знаєте, який код в 1.2? Хлопець просто робив копії коду та блискав на жорсткому диску?
liberforce

5

Не думайте з точки зору зміни рядків. Подумайте на шматки функціональності. VCS дозволяють задавати заголовок у центральному місці для кожного фрагмента функціональності, щоб ви могли легко бачити "що тут сталося", наприклад, журнал git.

Також IDE, як Eclipse, дозволяє вам вказувати на заданий рядок і переходити до комітету, який привів його у форму, яку ви бачите. Іншими словами, ви можете перейти безпосередньо від вихідної лінії до комітки. Якщо комісія невелика і має гарне повідомлення, це набагато корисніше, ніж "виправлені тонни помилок".


4

Я б сказав, що найголовніше, що вам не вистачає, групуючи зміни, наприклад, це можливість відстежувати, коли і де були введені помилки.

На моєму досвіді, кілька разів помічали помилку через два-три тижні після її введення, і необхідність пересідати цінні тижні зобов’язань важко, але довго після факту. У цих випадках було корисним просто двійковий пошук через коміти, щоб відстежити, які окремі зміни спричинили проблему. Ці помилки були в основному помилками використання пам'яті на C ++-коді, тому це може траплятися не так часто для вашого проекту.

Інші переваги вступають у гру при розробці команди - прості коментарі для фіксації, простіші злиття, пов’язання з виправленнями помилок тощо

З вашим робочим процесом я здогадуюсь, що якщо ви почнете робити щоденні чи напівденні, вам потрібно буде використовувати теги чи закладки, щоб відслідковувати, яка версія коду використовується на веб-сайті в реальному часі. Я б сказав, що це найважливіше, що слід слідкувати.


4

Я теж сольний розробник, використовую SVN, і мені це подобається. Я навіть написав інструмент для перетворення структури моєї бази даних та тестових даних у ній у xml, щоб я міг включити це в керування джерелами.

Зазвичай я беру на себе зобов’язання, коли я закінчив автономний блок роботи. Іноді, якщо я виконую купу тривіальних і неспоріднених однорядкових виправлень тут і там, то я ввожу їх усі разом, але якщо трапляється однорядковий виправлення між двома непов'язаними великими автономними одиницями роботи, то воно отримує свою власну вчинити, в цьому немає нічого поганого.

Також я завжди фіксую код, який компілює, і майже завжди код, який також проходить усі основні тести. Якщо ні, то я обов’язково включте "НЕ ПРАЦЮЄ" у повідомленні про фіксацію. Єдиний випадок, коли це відбувається - це коли я зробив важливі зміни, які я не хочу втратити, хоча вони ще не дуже працюють, і на додаток до цього я збираюся розпочати велику рефакторну пригоду, в якій я не впевнений, чи це буде успішним. Тож я використовую сховище як резервну копію роботи, яку я зробив до цього часу, перш ніж ризикувати зіпсувати його і доведеться викинути.

Це означає, що я завжди здійснюю, коли мій вихідний код потрібно вводити; абсолютно не має сенсу правил ранкової фіксації чи вечірнього вчинення. Саме стан коду полягає в тому, що диктує, чи потрібно час вчиняти.

Повідомлення, які ви поміщаєте в сховище, не мають великого значення. Якщо ви абсолютно не можете придумати щось значуще, все-таки краще взяти на себе зобов'язання з порожнім повідомленням, ніж взагалі не брати на себе зобов’язання.

Якщо ви не можете придумати гарне повідомлення про вчинення, оскільки все, що ви придумали, звучить нерозумно, майте на увазі, що це нормально; Очікується, що повідомлення про введення повідомлять про очевидне, тому вони обов'язково здадуться вам дурними, коли ви пишете їх. Але повірте, якщо вам доведеться вивчити старі версії через місяць, ви будете вдячні навіть за дурні повідомлення за жодні повідомлення.


1

Здійснюйте щоразу, коли ви робите "логічні" зміни. Наприклад, якщо ви реалізуєте нову функцію, ви робите це покроково. Кожен з цих кроків зазвичай залежить один від одного. Таким чином, ви можете просто зробити ці кроки окремо та пояснити у повідомленні про необхідність виконання кожного кроку.

Повідомлення про вчинення дійсно важливе. Ви повинні уникати того, щоб говорити, що ви робите, розкажіть, чому ви це робите. Код вже документує зміни, але через 6 місяців ви будете раді бачити, чому ви їх зробили.

Це також корисно, якщо випадково хтось заскочить і ви більше не самотні. Навіть тільки для вас, чиста історія полегшує використання a, git blameщоб знати, коли і чому була змінена та лінія, що має помилку.

Здійснення невеликих змін замість великої зміни кульових грязей також дозволяє перевірити проміжний стан. Ви можете приховати зміни, якщо вам доведеться терміново випустити щось. Якщо ви ввели помилку, поки вона працювала раніше, ви можете зберігати та перевіряти, чи невдалі зміни вводять помилку, чи це було в старій версії.

Ви також можете розкрити силу цього, git bissectщо скаже вам про те, що ця неприємна помилка. Якщо комісія завдовжки 2000 рядків, вона все ще допомагає, але не так вже й багато ...

Інша справа, що це перший крок для постійної інтеграції (CI), а потім безперервного розгортання (CD). CI та ваші тести можуть бути запущені на новому здійсненні, отже, вони повідомляють вам кожен раз, коли ви натискаєте свої зміни, якщо вони щось порушують чи ні. Таким чином, ви можете знати, чи безпечно це розгортати чи ні, і отримувати повідомлення про це в момент введення проблеми, а не безпосередньо перед звільненням, коли ви поспішаєте.

Про ваші інші запитання:

  • не вчиняйте речі, які ви навіть не складали, якщо ви не готові переписати свою історію для цього (використовуючи git rebase --interactive).
  • зміна одного рядка заслуговує на зобов’язання, якщо воно має окрему мету (виправляє помилку або не пов’язана з вашими невміленими на даний момент змінами). Використовуйте git add --patchдля постановки їх.
  • не потрібно змушувати себе робити зобов’язання перед обідом, якщо у вас є важливі речі, які ви не можете дозволити собі втратити. У такому випадку, можливо, ви захочете здійснити в окремому відділенні свою незавершену роботу.
  • здійснення та переміщення до віддаленого сховища - це резервна копія. Якщо ви покладете на себе і натисніть лише раз на тиждень, ви можете в гіршому випадку втратити один тиждень роботи.

0

Як часто я повинен здійснювати вчинки?

Як соло-розробник я, як правило, зобов'язуюсь кожного разу, коли відчуваю, що зробив значні зміни, після базового тестування, і коли залишаю проект наприкінці ночі.

Чи повинна кожна зміна одного рядка взяти на себе зобов’язання?

Ні, якщо тільки одна зміна рядка істотно не змінить функцію чи помилку.

Чи потрібно зробити я перед будь-яким тестом (наприклад, принаймні для синтаксису / компіляції помилок, а потім доведеться повністю скасувати його, оскільки ідея не спрацювала або повідомлення є брехнею)?

Напевно, ні. Принаймні для мене більшу частину мого тестування та кодування виконуються на «робочій копії» і виконую зобов’язання після того, як я задоволений своїми змінами. У багатьох IDE це покаже мені, що змінилося до того, як я насправді взяв на себе зобов’язання, і дасть мені можливість додавати нотатки до комітету

Чи повинен я переконатися, що я виконую щоранку / вдень, перш ніж перестати працювати на вечерю, поки її ще свіже? Що мені не вистачає, маючи погані звички VCS?

Я не дуже добре знайомий з VCS або якими шкідливими звичками він викликає. Я думаю, що я здебільшого поділяв свою думку з цього приводу, відповідаючи на перше запитання.

У відповідь на загальне постульоване запитання, ви, здається, в основному використовуєте комітети як гілки, які адресовані в іншому пості відповідей. Я не впевнений, який IDE ви використовуєте, який має гарну історію скасування і т. Д., Але я не знайшов жодного, який, на мою думку, був гарним після перезавантаження IDE та переміщення між машинами.


I am not very familiar with VCS or what bad habits it causes.Щасливчик!
янніс

1
Я не впевнений, як я читав це неправильно кілька разів, але продовжував читати це як "VSS", як у безпечному джерелі Visual. Я досить знайомий з різними системами управління версіями, включаючи SVN та GIT, і часто використовую їх як соло розробника, але, мабуть, маю кілька шкідливих звичок, вважаючи, що я насправді не використовував їх у контексті великого сценарію для багатьох розробників. .
dbuell

Що ж, оскільки я боровся з SourceSafe більше 3 років, мій коментар все ще стоїть: Пощастило! Для прикладу, VSS6 може обробляти сховища розміром приблизно 200 Мб - 300 Мб, після цього, якщо вам пощастить, кілька файлів були б випадково пошкоджені. Звичайно, там, де багато виправлень і обхідних шляхів, і VSS ніколи не задумав MS бути повноцінним вк, але вважайте себе щасливим, що вам ніколи з цим не доводилося стикатися ...
yannis

0

Я звичний фахівець, і я виявив, що мені підходить, але, правда, мої повідомлення про вчинення майже завжди схожі,

Age:  9 mins [*] Working on implementing and testing PaintSystem.
Age: 17 mins [*] Working on implementing and testing PaintSystem.
Age: 37 mins [*] Working on implementing and testing PaintSystem.
Age: 52 mins [*] Working on implementing and testing PaintSystem.

Тому я не можу точно сказати, що внесення таких частих і звичних зобов’язань до моєї гілки (mercurial) саме заохочує найдокладніші журнали фіксації. Іноді я навіть вчиню код на півдорозі, якщо, скажімо, моя дружина попросить мене вийти на вечерю, після чого я просто поспішаю скопіювати і скористатись попереднім повідомленням "Робота над [...]".

Мої шаблони журналів фіксації зазвичай такі, "Working on [...] Working on [...] Working [...] Completed [...] Started working on [...] Working on [...] Completed [...] Started working on [...]"

З іншого боку, це врятувало мою недопалку. Іноді я стикаюся з кращим випадком, якого я не очікував і не перевіряв, і тоді часті зобов'язання допомагають мені зрозуміти, де саме я ввів помилку.

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

Чи повинна кожна зміна одного рядка взяти на себе зобов’язання?

Я вносив зміни в рядку раніше, але, як правило, хитрі, і, можливо, мені не вистачало часу. Мої зобов'язання не завжди нагадують досконалі та завершені одиниці роботи чи зміни. Як говорилося, іноді вони є лише результатом того, що моя дружина просить мене несподівано вийти на вечерю.

TBH, багато моїх зобов’язань, які слідують за такою "Working on [...]"схемою журналу, - це не моделювання когерентних одиниць змін (чому я часто не можу придумати повідомлення краще "Working on [...]"), а лише результат того, що я передихав, як зробити собі чашку кави. "Completed [...]"Повідомлення вказує на кінець цієї одиниці роботи, і я часто пишу набагато більш докладне повідомлення разом з першим "Started working on [...]"повідомленнями типу , коли я просто почати працювати над чим - то. Якщо ви в середньому здійснюєте так, як раз на 15 хвилин, то повідомлення "Робота над [...]" більше нагадують користувачів, що ставляться до того, що хтось може здійснити за один об'ємний комітет з більш детальним повідомленням.

Чи потрібно зробити я перед будь-яким тестом (наприклад, принаймні для синтаксису / компіляції помилок, а потім доведеться повністю скасувати його, оскільки ідея не спрацювала або повідомлення є брехнею)?

Я просто йду вперед і виконую це перед тим, як іноді навіть запускати тести (знову ж таки, якщо у мене була несподівана подія). Незважаючи на те, що я соло, я натискаю на сервер (лише один працює тут вдома по локальній мережі), який робить CI. Це може здатися непосильним, але не знаю, я звик спиратися на це на своїх колишніх робочих місцях. Плюс мені не хочеться турбуватися про те, щоб кожен раз вручну виконувати всі мої модулі та інтеграційні тести. Мені подобається, що це все прив’язане до просто штовхання. Якщо тест не вдасться, досить просто працювати вперед, де я регресую, виправляю помилку в останніх оборотах і продовжую продовжувати. Але це означає , що я принаймні будую код проти налагодження, перш ніж виконувати його.

Чи повинен я переконатися, що я виконую щоранку / вдень, перш ніж перестати працювати на вечерю, поки її ще свіже?

Мені подобається займатися перед тим, як вийти на вулицю і перерву між програмуванням. Я не дуже замислювався над тим, чому саме, поки не зіткнувся з цим питанням. Я гадаю, що це не дасть мені вибрати місце, де я залишився без журналу комісій, замість того, де я зупинився, що я можу відрізнятись тощо. Хм, мені потрібно повернутися до вас з цього приводу, оскільки це, можливо, теоретично не потрібно, враховуючи те, як часто я виконую. Я все ще відчуваю себе комфортніше вчиняти та натискати, перш ніж покинути комп’ютер з будь-якої причини. Дещо це може бути колишній психологічний страх, скажімо, після того, як я виїжджаю з комп’ютера, коли я виїжджаю, і коли менеджери проектів повертаються назад у дні, коли ми використовували SVN разом із дияволами, що іноді їздили тижнями, не роблячи дихання за шию і постійно нагадуючи нам перевіряти код якомога частіше, нагадуючи нам, що наш код - власність компанії. Крім того, це трохи ефективніше, особливо при натисканні, щоб мій процес CI міг почати виконувати всі тести, поки я відсутній, щоб я міг повернутися і побачити результати.

О, а іноді я трохи напиваюся після від'їзду, і зазвичай погана ідея намагатися написати складний код, будучи п'яним (хоча і не завжди; одного разу я придумав дійсно приємну систему контекстного меню після того, як мав момент еврики, будучи п'яним, але я мав як 6 пива, і це було не так складно кодувати). Якщо я спробую це зробити, принаймні я вчинив тверезо написаний код перед тим, як піти, щоб повернутися назад, замість того, щоб змішувати п’яний код з тверезим кодом, і в цей момент мій журнал фіксування може читати як, "Reverting back to code written before Jagermeister shots."я цього не роблю дуже часто, якщо я не отримав натхнення від п’яного коду, але в тих рідкісних випадках це справді допомогло мені зробити щось, перш ніж я вийшов і напився.


Правило для вас: якщо у вас є два послідовні дії з однаковими повідомленнями, ви майже напевно робите це неправильно. Або вони повинні бути одним фіксатором, або ви повинні з'ясувати, що в них відрізняється, і написати повідомлення журналу, що відображають цю різницю (наприклад, "визначити нові дані фарби" та "встановити дані фарби належним чином", а не "працювати над системою фарби" x2).
Marnen Laibow-Koser
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.