Репозиторий: что это и как с ним работать
Репозиторий — часть системы Git, которая позволяет программистам совместно работать над проектами. Этот инструмент облегчает жизнь IT-специалистам: с ним можно безопасно вносить изменения в программный код. Что такое Git, как работает и для чего нужен репозиторий — рассказываем в статье.
Что такое репозиторий простыми словами
- Локальный — расположен на одном компьютере, и работать с ним может только один человек.
- Централизованный — расположен на сервере, куда имеют доступ сразу несколько программистов.
- Распределенный — самый удобный вариант с облачным хранилищем. Главный репозиторий хранится в облаке, а его локальные копии — у разработчиков на компьютерах. Когда программист вносит правки в локальную версию, ее можно синхронизировать с удаленной. Получается, что в облаке всегда актуальный код.
Для работы с распределенными репозиториями нужен удобный сервис. Самые популярные — GitHub, GitLab и Bitbucket. У них понятный интерфейс, в котором можно управлять проектом, добавлять новые объекты и искать общедоступные репозитории.
Git — это система, которая позволяет контролировать версии приложения. Она сохраняет все подтвержденные изменения кода. Поэтому в любой момент можно отменить правки или исключить ненужные части кода.
Git-сервисы позволяют переключаться между ветками кода и просматривать коммиты. Объясним, что такое ветка и коммит, на примере сервиса GitLab.
Пример репозитория в GitLab — структура такая же, как в обычном файловом менеджере
Чтобы изменения отправились в репозиторий проекта, их нужно «закоммитить». Так называется отправка данных в репозиторий. Это действие нужно, чтобы в репозитории была четкая структура версий.
Коммит подтверждает, что изменения в коде финальные и их можно применять.
Пример коммита в системе GitLab. Сразу видно, кто, когда и какие изменения внес в репозиторий
В репозиториях существуют «ветки» — это важная особенность Git-систем. Ветка позволяет менять отдельные элементы кода, не вмешиваясь в основной код. Главная ветка называется master, дополнительные можно называть по-своему.
Так выглядит раздел с ветками в GitLab — они разделяются на активные и устаревшие. В меню можно посмотреть название, скачать или удалить всю ветку
Внутри ветки видно весь ход изменений. Например, что конкретно и в каких файлах изменили
Как работать с системой распределенных репозиториев
Системы распределенных репозиториев GitHub, GitLab и Bitbucket удобны по нескольким причинам:
- Через них легко координировать разработку, проводить и публиковать тесты.
- В них можно размещать открытый исходный код, чтобы разработчики скачивали его копии и по-своему изменяли. Благодаря таким энтузиастам появляются новые версии программ.
- Это полезный ресурс для программистов при трудоустройстве. Сервис заменяет «портфолио» разработчика: человек может дать доступ к своему репозиторию и показать примеры хорошего кода.
Как создать репозиторий
Для начала работы нужно создать аккаунт. Это можно сделать на главной странице сайта: достаточно ввести имя, контактную почту и придумать пароль.
Доступна регистрация по одному клику через действующие аккаунты в Google, GitHub, Twitter, Bitbucket и Salesforce
После регистрации открывается окно с доступными действиями. Здесь можно создать новый проект или группу для совместной работы, отправиться изучать проекты других участников или узнать больше о работе GitLab.
У сервиса минималистичный интерфейс, в котором можно быстро разобраться
В новом окне нужно выбрать действие с проектом:
- Создать новый: подходящий вариант для нового репозитория. Останется задать имя и адрес, описание, доступность и конфигурацию проекта.
- Создать по готовому шаблону: достаточно выбрать цель проекта, и сервис создаст репозиторий с нужными настройками. Например, для работы с Android- или iOS-приложениями.
- Импортировать готовый с GitHub или Bitbucket.
- Подключить внешний репозиторий к GitLab CI/CD.
CI/CD — это «непрерывная интеграция и непрерывная поставка». При таком подходе в код вносят частые небольшие изменения, чтобы ускорить процесс коллективной работы.
Продвинутые пользователи могут создать проект через командную строку — это базовый инструмент работы с Git
После ввода основных параметров проекта остается нажать Create project, и репозиторий готов.
Для тех, кто не знает, как добавить репозиторий к уже существующим: нужно нажать на знак плюса в верхней части страницы и выбрать New project/repository.
По клику откроется меню с выбором, какой проект нужно создать
Как создать SSH-ключ
Как подключить репозиторий к облаку: для этого нужен SSH-ключ. Он позволяет не вводить данные пользователя при каждом коммите. Чтобы создать ключ, нужно:
- Скачать на компьютер Git-клиент.
- После установки клиента запустить его и ввести ssh-keygen в командной строке.
- Придумать имя для файла с ключом и запомнить путь сохранения. По умолчанию для Windows это ваша пользовательская папка.
- Придумать пароль для файла. Если пароль не нужен, пропустите шаг, нажав клавишу Enter.
- Получить два файла с ключом. Один — локальный только для вас, второй — публичный, для копирования. Git создает их автоматически.
Git записывает все ваши действия. Так можно проверить, какое имя файла вы задали и куда сохранили
Следующим шагом надо найти в вашей папке публичный ключ. У него будет расширение .pub — следует открыть его в текстовом редакторе и скопировать весь текст.
Далее нужно перейти к настройкам пользователя GitLab и выбрать раздел SSH Keys. Здесь нужно вставить скопированный текст в поле Key, задать имя и срок действия ключа и нажать Add key.
Новый SSH-ключ готов. Теперь с его помощью можно связать локальный репозиторий на компьютере с облачным в GitLab
Как клонировать репозиторий
Это действие нужно, чтобы подключить ключ. Чтобы клонировать репозиторий в GitLab:
Эти данные нужно будет ввести в Git-клиент на компьютере.
Выводы
Репозиторий — функциональное средство для работы с кодом. Работа с Git-репозиторием в программировании не позволит потерять или безвозвратно испортить код. Любые правки всегда можно отменить.
Для работы с системой контроля репозиториев потребуется Git-клиент на компьютере — через него отправляют пакеты с кодом в облачное хранилище. Он бесплатный и доступен для разных операционных систем: Windows, Linux и macOS. Также во всех современных редакторах кода типа VS Code или Atom есть инструменты для работы с репозиториями и Git-платформами. Это может быть встроенная возможность или плагины.
Читайте также:
Паттерн ‘Репозиторий’ в ASP.NET
Одним из наиболее часто используемых паттернов при работе с данными является паттерн ‘Репозиторий’. Репозиторий позволяет абстрагироваться от конкретных подключений к источникам данных, с которыми работает программа, и является промежуточным звеном между классами, непосредственно взаимодействующими с данными, и остальной программой.
Допустим, у нас есть одно подключение к базе данных MS SQL Server. Однако, что если в какой-то момент времени мы захотим сменить подключение с MS SQL на другое — например, к бд MySQL или MongoDB. При стандартном подходе даже в небольшом приложении, осуществляющем выборку, добавление, изменение и удаление данных, нам бы пришлось сделать большое количество изменений. Либо в процессе работы программы в зависимости от разных условий мы хотим использовать два разных подключения. Таким образом, репозиторий добавляет программе гибкость при работе с разными типами подключений.
Например, у нас в программе есть следующий класс модели, с которой мы работаем:
public class Book < public int Id < get; set; >public string Name < get; set; >public string Author < get; set; >public int Price < get; set; >>
И также имеется следующий класс контекста данных:
public class BookContext : DbContext < public BookContext() : base("DefaultConnection") < >public DbSet Books < get; set; >>
Пусть в файле web.config у меня определено два подключения:
Первое подключение используется контекстом данных для работы с бд MS SQL Server. Второе подключение — подключение к БД MongoDB.
Теперь определим интерфейс репозитория:
interface IRepository : IDisposable where T : class < IEnumerableGetBookList(); // получение всех объектов T GetBook(int id); // получение одного объекта по id void Create(T item); // создание объекта void Update(T item); // обновление объекта void Delete(int id); // удаление объекта по id void Save(); // сохранение изменений >
В данном случае мы создали обобщенный интерфейс, так как он более гибкий, по сравнению с обычной. Хотя так как у нас работа идет только с классом Book, можно было бы сделать и необобщенный вариант:
interface IRepository : IDisposable < IEnumerableGetBookList(); Book GetBook(int id); void Create(Book item); void Update(Book item); void Delete(int id); void Save(); >
На случай, если контекст данных будет подразумевать освобождение или закрытие подключений, интерфейс репозитория применяет интерфейс IDisposable.
Теперь создадим непосредственную реализацию для работы с MS SQL Server:
public class SQLBookRepository : IRepository < private BookContext db; public SQLBookRepository() < this.db = new BookContext(); >public IEnumerable GetBookList() < return db.Books; >public Book GetBook(int id) < return db.Books.Find(id); >public void Create(Book book) < db.Books.Add(book); >public void Update(Book book) < db.Entry(book).State = EntityState.Modified; >public void Delete(int id) < Book book = db.Books.Find(id); if(book!=null) db.Books.Remove(book); >public void Save() < db.SaveChanges(); >private bool disposed = false; public virtual void Dispose(bool disposing) < if(!this.disposed) < if(disposing) < db.Dispose(); >> this.disposed = true; > public void Dispose() < Dispose(true); GC.SuppressFinalize(this); >>
Почти все методы SQLBookRepository работают с контекстом данных, который создается в конструкторе класса.
Теперь применим репозиторий в контроллере:
public class HomeController : Controller < IRepositorydb; public HomeController() < db = new SQLBookRepository(); >public ActionResult Index() < return View(db.GetBookList()); >public ActionResult Create() < return View(); >[HttpPost] public ActionResult Create(Book book) < if(ModelState.IsValid) < db.Create(book); db.Save(); return RedirectToAction("Index"); >return View(book); > public ActionResult Edit(int id) < Book book = db.GetBook(id); return View(book); >[HttpPost] public ActionResult Edit(Book book) < if (ModelState.IsValid) < db.Update(book); db.Save(); return RedirectToAction("Index"); >return View(book); > [HttpGet] public ActionResult Delete(int id) < Book b = db.GetBook(id); return View(b); >[HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id) < db.Delete(id); return RedirectToAction("Index"); >protected override void Dispose(bool disposing) < db.Dispose(); base.Dispose(disposing); >>
В данном случае в всех методах контроллера мы работаем не с методами конкретного класса, а с методами интерфейса IRepository. И только в конструкторе контроллера мы определяем непосредственный тип репозитория: db = new SQLBookRepository(); . Таким образом, мы практически избавляемся от зависимости к определенному типу подключения.
Но у меня в файле web.config определено еще подключение к MongoDB. И теперь создадим репозиторий, который будет использовать это подключение:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.Builders; using System.Configuration; public class MongoBookRepository : IRepository < MongoClient client; MongoServer server; MongoDatabase database; public MongoBookRepository() < var con = new MongoConnectionStringBuilder( ConfigurationManager.ConnectionStrings["MongoDb"].ConnectionString); client = new MongoClient(con.ConnectionString); server = client.GetServer(); database = server.GetDatabase(con.DatabaseName); >public MongoCollection Books < get < return database.GetCollection("books"); > > public IEnumerable GetBookList() < return Books.FindAll(); >public Book GetBook(int id) < return Books.FindOneById(id); >public void Create(Book book) < try < int if (Books.Count() >0) => x.Id); book.Id = ++id; Books.Insert(book); > catch < >> public void Update(Book book) < try < Books.Save(book); >catch < >> public void Delete(int id) < try < var query = Query.EQ(e => e.Id, id); if (query != null) < Books.Remove(query); >> catch < >> public void Save() <> public void Dispose() <> >
Для работы с MongoDB используется другой API, однако, так как класс MongoBookRepository применяет тот же интерфейс репозитория, то общий набор методов у этого класса будет то же, что и у SqlBookRepository. Поэтому при необходимости можно просто заменить в контроллере тип репозитария:
А весь остальной код будет тем же, что и раньше. Таким образом, мы можем уйти от явной привязки к одному хранилищу данных и тем самым повысить гибкость приложения.