Продолжаю открывать для себя возможности системы Git и сервиса GitHub.

Уже сейчас, обладая минимальными базовыми знаниями Git и владея учетной записью на сервере GitHub, я не представляю, как я мог жить раньше без обоих этих вещей. Это действительно удобно и надежно!

Благодаря им я знаю, что у меня никогда и ничто не потеряется; и все, что нужно - у меня всегда под рукой. На работе поработал над чем-либо - отправил на GitHub; домой пришел - “стянул” наработки с GitHub и продолжил работу с прерванного места.

Вот на последнем я хотел бы остановиться подробнее. Конечно, веб-разработчик, давно и хорошо знакомый с Git и GitHub, может только улыбнуться насчет того, чем я собираюсь поделиться. Настолько все это просто и понятно. Но это просто и понятно для него, опытного web-разработчика. А для начинающего веб-программиста - это новое и неизведанное. Впрочем, достаточно лирики - переходим к практике.

GitHub - команда push

В предыдущей статье я познакомился с возможностью создания репозитория на сервисе GitHub. И возможностью клонирования этого репозитория на локальную машину - “GitHub и Git - создание и работа с репозиторием”.

Напомню, что в том примере было произведено клонирование репозитория с помощью команды:

$ git clone git@github.com:gearmobile/arbeit.git

Другими словами, было произведено копирование существующего репозитория с удаленного сервера на локальную машину. Причем, копирование как есть - полностью весь репозиторий, со всеми его файлами, коммитами, индексами и тому подобным.

После внесений изменений в локальный репозиторий - индексации и фиксации - необходимо было отправить произведенные изменения на удаленный сервер, на GitHub.

Для этой цели существует (и я ею воспользовался) команда push (отправить). К примеру, давайте я внесу еще кое-какие изменения в локальном репозитории, затем проиндексирую и зафиксирую их, а затем отправлю на GitHub:

$ git add .

$ git commit -m 'Continue write article about push and pull in GitHub'
[master 5af3abc] Continue write article about push and pull in GitHub
 1 file changed, 18 insertions(+)

$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

$ git push
...
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 1.65 KiB | 0 bytes/s, done.
Total 4 (delta 1), reused 0 (delta 0)
To git@github.com:semenencko/articles
   022b756..5af3abc  master -> master

Вот - все наработки, которые я сделал на домашнем компьютере, оказались с считанные секунды помещенными на сервере GitHub, под бдительным оком Git.

GitHub - команда pull

Продолжим логическую картину моего рабочего процесса (workflow). На следующий день я прихожу на работу и у меня есть время и возможность поработать над своим проектом. Естественно, я хочу продолжить с того места, на котором остановился дома. Для этого я воспользуюсь командой pull, чтобы “стянуть” с GitHub последние изменения.

В данном случае команда pull будет выглядеть так:

GitHub - команда pull

В выводе консоли (на картинке) видно, что было произведено добавление одного измененного файла по имени README.md, в котором были добавлены две строки.

Обратите внимание на разницу между командами clone и pull в данном случае. Команда clone копирует весь репозиторий целиком, как есть - со всеми его файлами. Команда pull копирует разницу между удаленным и локальным репозиторием. Эту разницу можно назвать дельта или patch.

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

GitHub - команда fetch

Существует разновидность команды pull - это команда fetch. И одна, и вторая команда выполняют одинаковые задачи - получение patch удаленного репозитория. Но делают они это по разному.

Команда pull получает patch репозитория и автоматически производит слияние удаленной и локальной ветвей репозитория. Если произойдет конфликт слияния, то только в этом случае слияния не произойдет и решать конфликт придется вручную.

Команда fetch также производит получение patch удаленного репозитория. Но при этом автоматического слияния ветвей удаленного и локального репозиториев не происходит:

GitHub - команда fetch

На картинке выше показано, что была выполнена команда git fetch после того, как на стороне сервиса GitHub было произведено редактирование файла README.md. Однако, последующая команда git status показала, что изменения есть, но они не слиты с локальной ветвью репозитория. И порекомендовала выполнить команду git pull, чтобы произвести такое слияние.

Помимо этого, имеются изменения в локальном репозитории, которые не проиндексированы и не зафиксированы. Что же, исправляю ситуацию - последовательно ввожу команды:

$ git pull
$ git add .
$ git commit -m 'Added fetch image'
$ git push

Производить слияние и разрешение конфликтов при слиянии я еще не умею, поэтому вопрос, как произвести слияние ветвей после команды git fetch я опущу в данной статье.

Вернувшись к вышесказанному, можно сделать вывод, что команда pull более универсальная, нежели команда fetch. Именно команду pull имеет смысл применять в практической работе.


Как новичок в работе с системой GitHub, столкнулся с вопросом - как удалить созданный на GitHub репозиторий?

Оказалось, что ничего сложного в этом нет. Однако, задача эта и не такая простая, как может показаться. По крайней мере, чисто интуитивно у меня не получилось ее выполнить - пришлось искать ответ в Сети.

Итак, у меня есть учетная запись на GitHub, под которой создана пара репозиториев. Один из этих репозиториев был создан в учебных целях, поэтому для моей дальнейшей работы он мне не пригодиться и его можно удалить.

Список репозиториев на GitHub

Для начала открою свою страничку на GitHub и посмотрю, какие репозитории у меня уже есть:

Список репозиториев на GitHub

Один из репозиторев - arbeit - можно удалить.

Для этой цели нужно просто зайти в него по ссылке:

Репозиторий arbeit на GitHub

В правом нижнем углу окна браузера, в списке, имеется строка Settings. Открываем ее, сразу же копируем имя репозитория в поле Repository name (оно нам понадобиться еще здесь) и прокручиваем страницу вниз, пока не находим раздел с устрашающим названием Danger Zone. В этой опасной зоне находим подраздел Delete this repository с одноименной кнопкой Delete this repository.

Жмем на эту кнопку и получаем в результате окно с предупреждением об удаленни репозитория. В окне запроса имени удаляемого репозитория вводим (или вставляем из буфера обмена) - arbeit:

Запрос имени удаляемого репозитория

Снова жму на кнопку, на этот раз с еще более страшным напоминанием о последствиях совершаемого мною шага. И все! Репозиторий arbeit удален:

Удаленный репозиторий на GitHub

Ничего сложного, но так сразу и не догадаешься, что нужно делать. Разработчики GitHub постарались и обезопасили пользователей от случайного удаления репозиториев с данными.


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

Вот такие получаются шаги, которые нужно осветить. Profit у всех этих сложностей, описанных мною выше, один - но большой! Заключается он в том, что проект, над которым вы работаете (даже в гордом одиночестве) находится на удаленном сервере, к которому можно подключиться из любого места и с любой машины. Так как он находиться на remote server, то с ним ничего не случиться, даже если ваша машина упадет\утонет\разобьется.

В статье большая часть времени будет посвящена автоматизации процесса авторизации на сервисе GitHub с помощью такой вещи, как ssh-ключи. Такие ключи предназначены как раз для возможности авторизации пользователя на каком-либо сервисе, без необходимости каждый раз вводить логин\пароль. Естественно, на стороне сервиса должна быть настроена такая возможность - на GitHub она настроена и даже является почти обязательным условием настройки аккаунта.

Все действия, описанные в этой статье, будут производиться под операционной системой Linux Mint 17 Cinnamon, в консоли. Поэтому пользователи Mac OS X найдут для себя почти все идентичным. Система Windows остается в стороне.

Создание SSH-ключей под Linux

Первоначально необходимо создать (если их еще нет) ssh-ключи, которые будем использоваться для авторизации на GitHub. В системе Linux такие ключи расположены в домашней директории пользователя и выглядят примерно так:

$ ls ~/.ssh
  id_rsa id_rsa.pub known_hosts

Один из этих ключей id_rsa - это приватный ключ, который должен храниться только у пользователя. Другой ключ id_rsa.pub - это публичный ключ, который предоставляется всем и который я отправлю на GitHub. Представленные выше имена ключей являются создаваемыми по умолчанию, но можно указать и свои собственные.

Если показанная выше команда “скажет” вам, что директории .ssh не существует, то это означает, что у вас с системе установлен пакет SSH, отвечающий за создание и обработку ssh-ключей.

Установка пакета SSH

Под Linux Mint его нужно установить командой:

$ sudo apt-get install ssh

Создание пары ssh-ключей

Теперь можно приступать к созданию пары ssh-ключей. Выполняется это командой:

$ ssh-keygen -t rsa -C "g***e@gmail.com"

Чтобы было немного понятно, что это я сделал в данной команде, немного расшифрую ее. Утилита ssh-keygen входит в комплект пакета ssh и предназначена для одной цели - создания ssh-ключей. Часть команды - -t rsa - указывает, что необходимо создать ssh-ключи типа rsa.

Обязательный параметр "g***e@gmail.com" - электронный адрес, к которому “привязывается” создаваемый ssh-ключ; данный email будет также использоваться мною для регистрации на GitHub.

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

$ ssh-keygen -t rsa -C "g***e@gmail.com"
  Generating public/private rsa key pair.
  Enter file in which to save the key (/home/aaron/.ssh/id_rsa):

Утилита задаст еще один вопрос, который крайне не рекомендуется игнорировать:

$ ssh-keygen -t rsa -C "g***e@gmail.com"
  Generating public/private rsa key pair.
  Enter file in which to save the key (/home/aaron/.ssh/id_rsa):
  Enter passphrase (empty for no passphrase):

Здесь passphrase - это пароль к создаваемым ssh-ключам. Каждый раз, когда придется использовать эти ключи, нужно вводить данный пароль. Это обезопасит их в случае кражи. В качестве пароля можно использовать любую текстовую строку.

После успешного ввода passphrase ssh-ключи будут созданы:

$ ssh-keygen -t rsa -C "g***e@gmail.com"
  Generating public/private rsa key pair.
  Enter file in which to save the key (/home/aaron/.ssh/id_rsa):
  Enter passphrase (empty for no passphrase):
  Enter same passphrase again:
  Your identification has been saved in /home/aaron/.ssh/id_rsa.
  Your public key has been saved in /home/aaron/.ssh/id_rsa.pub.

В состав пакета ssh входит утилита ssh-agent, задача которой в управлении созданными ssh-ключами. Передадим ей в пользование только созданные мною ssh-ключи:

$ eval "$(ssh-agent -s)"
  Agent pid 17461
  $ ssh-add ~/.ssh/id_rsa
  Enter passphrase for /home/aaron/.ssh/id_rsa:
  Identity added: /home/aaron/.ssh/id_rsa (/home/aaron/.ssh/id_rsa)

Можно посмотреть, что утилита shh-add “подхватила” и распознала предоставленные ею ssh-ключи:

$ ssh-add -l
  2048 e4:4d:fe:73:cb:b9:bb:ee:26:32:6b:f5:f1:6a:db:38 /home/aaron/.ssh/id_rsa (RSA)

Под операционную систему Linux имеется консольная утилита xclip, которая умеет получать содержимое любого файла и отправлять это содержимое в буфер обмена, и все это в консоли. По умолчанию такой утилиты нет в системе (в том числе и у меня), поэтому первоначально установлю ее:

$ sudo apt-get install xclip

… а затем передам ей на вход содержимое публичного ключа id_rsa.pub, который буду применять на сервисе GitHub:

$ xclip -sel clip < ~/.ssh/id_rsa.pub

Если вам, уважаемый читатель, такой путь покажется слишком сложным, то можно открыть файл id_rsa.pub в любом редакторе кода и скопировать его содержимое в буфер обмена.

Добавление ssh-ключа на GitHub

Переходим на сервис GitHub и создаем на нем новую учетную запись. Описывать процесс создания такой записи на GitHub не буду, так как там все просто. Более интересный момент - это добавление ssh-ключа в профиль пользователя GitHub.

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

SSH ключи на GitHub

Откроется окно для добавления новых ssh-ключей в учетную запись пользователя на GitHub. Здесь все элементарно просто - нажимаем кнопку Add SSH key. В поле Title вводим название (произвольное) для импортируемого ssh-ключа.

В поле Key просто нажимаем Ctrl+V - содержимое буфера обмена (которое я получил ранее с помощью утилиты xclip) вставиться в это поле:

Добавление ssh-ключа на GitHub

Жму на зеленую кнопку Add key внизу окна. Ключ добавлен на GitHub и появиться в списке SSH-ключей:

Добавленный на GitHub ssh-ключ

Проверка SSH-соединения с GitHub

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

Для этой цели ввожу команду:

$ ssh -T git@github.com
  The authenticity of host 'github.com (192.30.252.131)' can't be established.
  RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
  Are you sure you want to continue connecting (yes/no)? yes

На ошибку в строке The authenticity of host 'github.com (192.30.252.131)' can't be established. не стоит обращать внимание. В запросе командной строки печатаем yes и получаем:

Warning: Permanently added 'github.com,192.30.252.131' (RSA) to the list of known hosts.
Hi gearmobile! You've successfully authenticated, but GitHub does not provide shell access.

Отлично! GitHub “узнал” меня и поприветствовал в строке Hi gearmobile! You've successfully authenticated, but GitHub does not provide shell access.. Это говорит о том, что ssh-соединение моей машины с GitHub установлено успешно и GitHub авторизует меня.

Однако, при настройке ssh-соединения возможны и ошибки. В этом случае может помочь статья - Error: Permission denied (publickey).

Создание нового репозитория на GitHub

Создаем новый репозиторий на GitHub. Ввожу новое уникальное имя для репозитория, краткое его описание и включаю галочку “Initialize this repository with a README”:

Создание нового репозитория на GitHub

Отлично! На GitHub я только что создал новый репозиторий arbeit. Теперь можно скопировать (склонировать) его на свою локальную машину командами:

$ mkdir arbeit
$ git clone git@github.com:gearmobile/arbeit.git
  Cloning into 'arbeit'...
  Warning: Permanently added the RSA host key for IP address '192.30.252.130' to the list of known hosts.
  remote: Counting objects: 3, done.
  remote: Compressing objects: 100% (2/2), done.
  remote: Total 3 (delta 0), reused 0 (delta 0)
  Receiving objects: 100% (3/3), done.
  Checking connectivity... done

Переходим в локальную копию репозитория arbeit. Вношу изменения, а затем последовательно:

$ git add .
$ git commit -m 'Added changes'
$ git push

Команда git commit -m 'Added changes' фиксирует изменения в локальном репозитории. Команда git push отправляет внесенные и зафиксированные изменения в локальном репозитории на удаленный репозиторий.

Вот, таким образом я наладил Git-работу своей машины с GitHub.


В системе Git можно настроить возможность автоматического игнорирования файлов.

То есть, можно указать Git, что файлы определенного типа не нужно отслеживать. Выполняется такая настройка с помощью специального файла .gitignore. Подобная возможность отключения отслеживания файлов в системе Git может понадобиться в случае, когда автоматически генерируются служебные файлы.

К примеру, если развертывать в проекте Compass, то будет создан каталог .sass, в который данный фреймворк помещает свой кэш, генерируемый автоматически при каждом изменении любого из файлов проекта.

Давайте на практике разберемся, каким образом можно настроить игнорирование файлов в Git с помощью .gitignore.

Создание нового проекта

Создаю новый проект с именем git_ignore, в котором помещаю несколько файлов разного типа:

$ mkdir git_ignore
$ cd git_ignore/
$ touch index.html style.css

Инициализирую репозиторий Git в директории .git_ignore, индексирую созданные файлы и фиксирую их:

$ git init
Initialized empty Git repository in /home/aaron/Projects/git_ignore/.git/
$ git add .
$ git commit -m 'First Commit'

Вывод команды git status показывает, что все чисто:

$ git status
On branch master
nothing to commit, working directory clean

Настройка игнорирования в .gitignore

Для настройки игнорирования определенных типов файлов в системе Git необходимо первоначально создать файл .gitignore:

$ touch .gitignore

Откроем созданный файл .gitignore в любом редакторе:

$ nano -w .gitignore

… и пропишем в нем следующие строки:

*.txt
*.md

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

Проиндексируем и зафиксируем изменения (создание файла настроек .gitignore), а затем проверим данный факт. Для этого в рабочей директории git_ignore создаю еще несколько типов файлов:

$ touch main.css readme.txt humans.md

Затем выполняю индексацию всех файлов, которые были добавлены или изменены в рабочем каталоге:

$ git add .

И смотрю, что мне показывает команда git status:

$ git status
  On branch master
  Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

    new file:   main.css

Система Git увидела только новый файл main.css. Два других файла - readme.txt и humans.md - проигнорированы системой. Отлично! Зафиксирую изменения.

Можно создать еще пару файлов в разных директориях и посмотреть на вывод команды git status в консоли:

Результат настройки файла .gitignore

Усложнить задачу игнорирования в .gitignore

Можно усложнить задачу игнорирования в Git, добавив в файл .gitignore директорию, содержимое которой также должно игнорироваться. Пускай это будет обычная директория ignore и скрытая директория .ignore (с точкой перед именем):

Добавлю в файл .gitignore пару строк таким образом:

$ cat .gitignore
*.txt
*.md
ignore/
.ignore/

Проиндексирую изменения, а затем выполню операции по созданию директорий и файлов внутри них:

$ mkdir ignore
$ mkdir .ignore
$ touch ignore/reset.css
$ touch .ignore/normilize.css

Вновь ввожу команду просмотра состояния репозитория Git:

$ git status
  On branch master
  nothing to commit, working directory clean

Все сработало - Git не захотел видеть директории ignore, .ignore, а также их содержимое. Отлично!

Шаблоны в файле .gitignore

Для файла .gitignore доступны шаблоны, с помощью которых можно задать маски для выборки необходимых типой файлов. Однако, обширная тема шаблонов выходит за рамки данной статьи. При желании можно почитать по теме шаблонов в книге “Pro Git - профессиональный контроль версий”.


Сегодня рассмотрим еще один очень нужный и полезный плагин для web-разработчика. Это плагин gulp-livereload под Gulp, который должен иметь каждый веб-разработчик в своей копилке.

Суть плагина gulp-livereload в автоматизации обновления страниц в окне браузера. Это тоже самое, что и связка - плагин LiveReload под Sublime Text + плагин LiveReload под браузер. Но в данном случае получается связка - плагин gulp-livereload + плагин LiveReload под браузер.

Сказать честно, предыдущий опыт настройки LiveReload, описанный в этой статье - “Установка LiveReload в Sublime Text 2” меня полностью не удовлетворял и я им не пользовался. Причина заключалась в том, что иногда эта связка работала, а иногда - почему-то нет. Нестальность работы плагина под Sublime Text (у меня) отбивала всякое желание иметь с ним дело.

А вот связка плагин gulp-livereload + плагин LiveReload под браузер работает стабильно. Кроме того, если Node.js + Gulp уже настроен для текущего проекта, то не возникает никакой проблемы в установке дополнительного плагина gulp-livereload.

Установка плагина gulp-livereload

Плагин gulp-livereload проживает по указанному адресу - gulp-livereload. Установка в проект производиться командой:

$ npm install --save-dev gulp-livereload

В виде зависимостей проекта запись в файле package.json должна выглядеть (как минимум) так:

{
 "name": "test",
 "version": "0.0.1",
 "devDependencies": {
  "gulp": "~3.8.7",
  "gulp-livereload": "~2.1.1"
 }
}

Добавляем переменную livereload в файл gulpfile.js для инициализации плагина gulp-livereload и дальнейшей работы с ним:

var gulp = require('gulp'),
    livereload = require('gulp-livereload');

Установка плагина LiveReload под браузер

Следующим шагом будет установка расширения LiveReload под браузер. В моем случае это будет Mozilla Firefox, однако расширение LiveReload существует и под два других популярных браузера - Google Chrome и Safari.

Для установки расширения под Firefox не стоит искать его на странице расширений Mozilla - LiveReload 0.6.4. Там находится устаревшая версия плагина, которая наверняка не подойдет для вашего браузера.

Лучше посетим домашнюю страницу проекта LiveReload с описанием установки расширений под каждый из браузеров - How do I install and use the browser extensions. Скачиваем по указанной на странице ссылке расширение под нужный браузер (Firefox) и автоматически устанавливаем его.

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

Создание задачи под gulp-livereload

В принципе, плагин gulp-livereload не требует для себя создания отдельной задачи. Все, что нужно для него - это запуск его как локального сервера. Если вы скажете, что не устанавливали сервер LiveReload, то могу успокоить вас - устанавливали! Инсталляция плагина gulp-livereload подразумевает автоматическую установку сервера LiveReload.

Поэтому нам нужно всего лишь предварительно активировать, запустить его. Кстати, если у вас вдруг при попытке включения плагина LiveReload в браузере появляется окно с такой ошибкой:

Ошибка запуска сервера LiveReload

… то это говорит всего лишь о том, что перед этим не был запушен в консоли сам сервер LiveReload. Для этого я создам задачу watch, внутрь которой помещу вызов функции livereload():

// Watch Task
 gulp.task('watch', function(){
  livereload.listen();
  gulp.watch('sass/*.scss', ['sass']).on('change', livereload.changed);
});

Все - мне больше ничего не нужно дописывать для задачи компилирования из Sass в CSS (эта задача приведена здесь в качестве примера использования плагина gulp-livereload):

// Sass Complie Task
 gulp.task('sass', function(){
 gulp.src('sass/*.scss')
  .pipe(sassSCSS())
  .pipe(gulp.dest('build/css'));
});

Полностью листинг файла gulpfile.js в данном случае будет выглядеть таким образом:

var gulp = require('gulp'),
    sassSCSS = require('gulp-sass'),
    minifyHTML = require('gulp-minify-html'),
    rename = require('gulp-rename'),
    livereload = require('gulp-livereload');

// Default Task
gulp.task('default', ['sass', 'watch']);

// Watch Task
 gulp.task('watch', function(){
  livereload.listen();
  gulp.watch('sass/*.scss', ['sass']).on('change', livereload.changed);
});

// Sass Complie Task
gulp.task('sass', function(){
 gulp.src('sass/*.scss')
  .pipe(sassSCSS())
  .pipe(gulp.dest('build/css'));
});

Все готово для тестирования работы плагина gulp-livereload.

Тестирование плагина gulp-livereload

Осталось выполнить две маленькие вещи. Первая - включаю плагин LiveReload в браузере. Вторая - запускаю Gulp для мониторинга изменений и работы плагина gulp-livereload:

$ gulp
Using gulpfile ~/Projects/gulp_test/gulpfile.js
Starting 'sass'...
Finished 'sass' after 11 ms
Starting 'watch'...
Finished 'watch' after 17 ms
Starting 'default'...
Finished 'default' after 19 μs
Live reload server listening on: 35729

Видим, как последняя строка в консоли говорит нам, что сервер LiveReload запустился и прослушивает порт по умолчанию - 35729. Вношу изменения в файл стилей style.scss:

figure{
  border: 1px solid #000;
  padding: 5px;
 }

… и смотрю на вывод в консоли:

$ gulp
Using gulpfile ~/Projects/gulp_test/gulpfile.js
Starting 'sass'...
Finished 'sass' after 10 ms
Starting 'watch'...
Finished 'watch' after 15 ms
Starting 'default'...
Finished 'default' after 11 μs
Live reload server listening on: 35729
style.scss was reloaded.
Starting 'sass'...
Finished 'sass' after 3.58 ms

Изменение было отслежено, файл перекомпилирован задачей sass. А что же плагин gulp-livereload - он тоже подхватил изменения?

Смотрим:

Изменения в gulp-livereload

О, да! Изменение было подхвачено плагином gulp-livereload - “картинка” в окне браузера изменилась без перезагрузки последнего.

Еще раз проверим и внесем какое-нибудь изменение в файле стилей:

$ gulp
Using gulpfile ~/Projects/gulp_test/gulpfile.js
Starting 'sass'...
Finished 'sass' after 10 ms
Starting 'watch'...
Finished 'watch' after 15 ms
Starting 'default'...
Finished 'default' after 11 μs
Live reload server listening on: 35729
style.scss was reloaded.
Starting 'sass'...
Finished 'sass' after 3.58 ms
style.scss was reloaded.
Starting 'sass'...
Finished 'sass' after 1.97 ms

Изменения в gulp-livereload

Отлично! Вот мы и изучили еще одну полезную сторону работы с Gulp - использование плагина gulp-livereload.