diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..5e96f00f --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +learnGitBranching.js.org diff --git a/README.md b/README.md index 25718f42..72a418ba 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ And the following heroes for assisting in translating: * Eroany H Leader ("lhyqy5") * Honorat ("ahonorat") * Vasil Kulakov ("coyl") & Lyubov Agadjanyan ("shayenblue") +* Aliaksei Berkau ("alexeiberkov") Also huge shoutout for everyone who has put up a pull request that was pulled! Check out the 30+ contributors we have in the [Contributors View](https://github.com/pcottle/learnGitBranching/graphs/contributors) diff --git a/package.json b/package.json index 2af25e75..d0216de9 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "react-tools": "^0.13.1" }, "dependencies": { - "backbone": "^1.1.2", + "backbone": "~1.1.2", "events": "^1.0.2", "flux": "^2.0.1", "jquery": "~1.7.3", diff --git a/src/js/__tests__/base.js b/src/js/__tests__/base.js index f408991e..5c8547c8 100644 --- a/src/js/__tests__/base.js +++ b/src/js/__tests__/base.js @@ -84,7 +84,7 @@ var expectTreeAsync = function(command, expectedJSON, startJSON) { console.log(JSON.stringify(getHeadlessSummary(headless))); } return compareAnswer(headless, expectedJSON); - }, 'trees should be equal', 100); + }, 'trees should be equal', 400); }; var expectLevelSolved = function(levelBlob) { diff --git a/src/js/intl/strings.js b/src/js/intl/strings.js index e66b3b0c..3eb08156 100755 --- a/src/js/intl/strings.js +++ b/src/js/intl/strings.js @@ -378,7 +378,9 @@ exports.strings = { /////////////////////////////////////////////////////////////////////////// 'git-warning-hard': { '__desc__': 'One of the warning messages for git', - 'en_US': 'The default behavior is a --hard reset, feel free to omit that option!', + 'en_US': 'The default behavior for resets on LearnGitBranching is a --hard, so feel free to omit ' + + 'that option if you get tired of typing it out in our lessons. Just remember that the default ' + + 'behavior on actual Git is --mixed.', 'de_DE': 'Das Standardverhalten in dieser Demo ist --hard, du kannst die Option auch weglassen!', 'zh_CN': '默认的行为是 --hard 硬重置,尽管省略掉那个选项吧!', 'zh_TW': '預設的行為是 --hard reset,儘量省略掉那個選項吧!', diff --git a/src/js/level/builder.js b/src/js/level/builder.js index 38e33ec0..d3e7b1a2 100644 --- a/src/js/level/builder.js +++ b/src/js/level/builder.js @@ -21,7 +21,6 @@ var MultiView = require('../views/multiView').MultiView; var CanvasTerminalHolder = require('../views').CanvasTerminalHolder; var ConfirmCancelTerminal = require('../views').ConfirmCancelTerminal; var NextLevelConfirm = require('../views').NextLevelConfirm; -var LevelToolbar = require('../views').LevelToolbar; var MarkdownPresenter = require('../views/builderViews').MarkdownPresenter; var MultiViewBuilder = require('../views/builderViews').MultiViewBuilder; @@ -45,6 +44,7 @@ var LevelBuilder = Level.extend({ initialize: function(options) { options = options || {}; options.level = {}; + this.options = options; var locale = LocaleStore.getLocale(); options.level.startDialog = {}; @@ -75,10 +75,6 @@ var LevelBuilder = Level.extend({ }, initName: function() { - this.levelToolbar = new LevelToolbar({ - name: intl.str('level-builder'), - parent: this - }); }, initGoalData: function() { @@ -97,7 +93,6 @@ var LevelBuilder = Level.extend({ this.doBothVis('hide'); this.goalWindowPos = position; this.goalWindowSize = size; - this.levelToolbar.$goalButton.text(intl.str('show-goal-button')); if ($('#goalPlaceholder').is(':visible')) { $('#goalPlaceholder').hide(); this.mainVis.myResize(); diff --git a/src/js/react_views/CommandView.jsx b/src/js/react_views/CommandView.jsx index 529d02cc..362c4a6e 100644 --- a/src/js/react_views/CommandView.jsx +++ b/src/js/react_views/CommandView.jsx @@ -71,7 +71,11 @@ var CommandView = React.createClass({
{'$'}
- {' ' + this.state.rawStr}
+ {' '}
+
diff --git a/src/js/views/builderViews.js b/src/js/views/builderViews.js
index f956e730..bdf41b0e 100644
--- a/src/js/views/builderViews.js
+++ b/src/js/views/builderViews.js
@@ -75,7 +75,7 @@ var MarkdownGrabber = ContainedBase.extend({
var confirmCancel = new Views.ConfirmCancelView({
deferred: buttonDefer,
destination: this.getDestination()
- }.bind(this));
+ });
}
this.updatePreview();
diff --git a/src/js/views/levelDropdownView.js b/src/js/views/levelDropdownView.js
index 889dd5fe..8f01aee0 100644
--- a/src/js/views/levelDropdownView.js
+++ b/src/js/views/levelDropdownView.js
@@ -281,7 +281,6 @@ var LevelDropdownView = ContainedBase.extend({
// also go find the series and update the about
_.each(this.seriesViews, function(view) {
if (view.levelIDs.indexOf(id) === -1) {
- view.resetAbout();
return;
}
view.updateAboutForLevelID(id);
@@ -354,8 +353,7 @@ var SeriesView = BaseView.extend({
template: _.template($('#series-view').html()),
events: {
'click div.levelIcon': 'click',
- 'mouseenter div.levelIcon': 'enterIcon',
- 'mouseleave div.levelIcon': 'leaveIcon'
+ 'mouseenter div.levelIcon': 'enterIcon'
},
initialize: function(options) {
@@ -365,7 +363,11 @@ var SeriesView = BaseView.extend({
this.levels = LevelStore.getLevelsInSequence(this.name);
this.levelIDs = [];
+ var firstLevelInfo = null;
_.each(this.levels, function(level) {
+ if (firstLevelInfo === null) {
+ firstLevelInfo = this.formatLevelAbout(level.id);
+ }
this.levelIDs.push(level.id);
}, this);
@@ -375,6 +377,7 @@ var SeriesView = BaseView.extend({
this.JSON = {
displayName: intl.getIntlKey(this.info, 'displayName'),
about: intl.getIntlKey(this.info, 'about') || " ",
+ levelInfo: firstLevelInfo,
ids: this.levelIDs
};
@@ -396,13 +399,8 @@ var SeriesView = BaseView.extend({
return $(element).attr('data-id');
},
- resetAbout: function() {
- this.$('p.about').text(intl.getIntlKey(this.info, 'about'))
- .css('font-style', 'inherit');
- },
-
setAbout: function(content) {
- this.$('p.about').text(content).css('font-style', 'italic');
+ this.$('p.levelInfo').text(content);
},
enterIcon: function(ev) {
@@ -411,12 +409,19 @@ var SeriesView = BaseView.extend({
},
updateAboutForLevelID: function(id) {
- var level = LevelStore.getLevel(id);
- this.setAbout(intl.getName(level));
+ this.setAbout(this.formatLevelAbout(id));
},
- leaveIcon: function() {
- this.resetAbout();
+ formatLevelAbout: function(id) {
+ var level = LevelStore.getLevel(id);
+ return this.getLevelNumberFromID(id) +
+ ': ' +
+ intl.getName(level);
+ },
+
+ getLevelNumberFromID: function(id) {
+ // hack -- parse out the level number from the ID
+ return id.replace(/[^0-9]/g, '');
},
click: function(ev) {
diff --git a/src/levels/remote/fakeTeamwork.js b/src/levels/remote/fakeTeamwork.js
index f6db4ba4..5b9a8f38 100644
--- a/src/levels/remote/fakeTeamwork.js
+++ b/src/levels/remote/fakeTeamwork.js
@@ -10,7 +10,8 @@ exports.level = {
"es_AR": "Simulando el trabajo en equipo",
"pt_BR": "Simulando trabalho em equipe",
"zh_CN": "模拟团队合作",
- "zh_TW": "模擬團隊合作"
+ "zh_TW": "模擬團隊合作",
+ "ru_RU": "Коллективная работа"
},
"hint": {
"en_US": "remember you can specify the number of commits to fake",
@@ -20,7 +21,8 @@ exports.level = {
"es_AR": "Acordate que podés especificar cuántos commits simular",
"pt_BR": "Lembre-se que você pode especificar quantos commits quer simular",
"zh_CN": "记住为fake中的commit指定数量",
- "zh_TW": "你要記得指定要送多少個 commit 出去"
+ "zh_TW": "你要記得指定要送多少個 commit 出去",
+ "ru_RU": "помните, Вы можете указать колличество фейковых коммитов"
},
"startDialog": {
"en_US": {
@@ -400,6 +402,60 @@ exports.level = {
}
}
]
+ },
+ "ru_RU": {
+ "childViews": [
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "## Simulating collaboration",
+ "",
+ "В данном уроке мы находимся в немного затруднительном положении -- для выполнения ряда упражнений нам нужно обучить Вас как скачивать наработки и изменения, которые были сделаны в удалённом репозитории.",
+ "",
+ "Это означает, что нам следует \"сделать вид\", как будто мы знаем о том, что наш удалённый репозиторий, с которым мы работаем, был изменён наработками, сделанными одним из Ваших коллег / друзей / единомышленников. Это может быть какая-то ветка либо же какой-то конкретный коммит.",
+ "",
+ "Для того, чтобы добится своих целей, нам предоставляется комманда со звучным именем `git fakeTeamwork`! Имя комманды однозначно даёт понят что она выполняет. Давайте ознакомимся с демо..."
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Поведение комманды `fakeTeamwork` по-умолчанию заключаентся в том, чтобы просто \"инициировать\" коммит на master-е"
+ ],
+ "afterMarkdowns": [
+ "Ну вот -- удалённый репозиторый был изменён при помощи добавления нового коммита, и мы не ещё не скачали этот коммит, потому что не запустили комманду `git fetch`."
+ ],
+ "command": "git fakeTeamwork",
+ "beforeCommand": "git clone"
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "В данной комманде Вам доступна возможность указать ветку и колличество добавляемых коммитов"
+ ],
+ "afterMarkdowns": [
+ "С помощью одной лишь комманды мы симулируем добавление трёх коммитов в ветку `foo` на удалённом репозитории"
+ ],
+ "command": "git fakeTeamwork foo 3",
+ "beforeCommand": "git branch foo; git clone"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Последующие уровни будут довольно сложными, поэтому в этом упражнении от Вас больше ничего не требуется.",
+ "",
+ "Вперёд! Склонируйте удалённый репозиторий (с помощью `git clone`), симулируйте какие-нибудь изменения на этом удалённом репозитории, сделайте какие-нибудь свои коммиты и затем скачайте \"чужие\" изменения. Это выглядит как несколько уроков в одном!"
+ ]
+ }
+ }
+ ]
}
}
};
diff --git a/src/levels/remote/fetchRebase.js b/src/levels/remote/fetchRebase.js
index b6f4beca..8b14dbc0 100644
--- a/src/levels/remote/fetchRebase.js
+++ b/src/levels/remote/fetchRebase.js
@@ -10,7 +10,8 @@ exports.level = {
"pt_BR": "Histórico divergente",
"de_DE": "Abweichende History",
"fr_FR": "Historique divergent",
- "ja" : "履歴の分岐"
+ "ja" : "履歴の分岐",
+ "ru_RU": "Расхождение в истории"
},
"hint": {
"en_US": "check out the ordering from the goal visualization",
@@ -20,7 +21,8 @@ exports.level = {
"ot_BR": "Preste atenção na ordem da visualização do objetivo",
"de_DE": "Beachte die Reihenfolge in der Zieldarstellung",
"ja" : "ゴールのビジュアライズの順番を参照",
- "fr_FR": "regardez l'ordre dans la fenêtre de visualisation d'objectif"
+ "fr_FR": "regardez l'ordre dans la fenêtre de visualisation d'objectif",
+ "ru_RU": "проверьте сортировку в визуализации цели"
},
"startDialog": {
"en_US": {
@@ -1023,6 +1025,149 @@ exports.level = {
}
}
]
+ },
+ "ru_RU": {
+ "childViews": [
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "## Когда наработки расходятся",
+ "",
+ "Вот мы и познакомились с тем, как забирать (`pull`) чужие коммиты и как закачивать (`push`) свои наработки и изменения. Выглядит всё довольно просто, и не ясно какие же могу возникать у людей трудности со всем этим ?",
+ "",
+ "Сложности возникают тогда, когда история репозитория *расходится*. Давайте посмотрим на пример прежде чем идти дальше...",
+ ""
+ ]
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Представьте себе, Вы склонировали репозиторий в понедельник и начали разрабатывать какую-то новую и уникальную часть приложения (на сленге разработчиков - `фича`). В пятницу вечером Вы наконец-то готовы опубликовать Вашу фичу. Но, о нет! Ваш коллега в течении недели написал кучу кода, который делает все Ваши наработки устарелыми. Этот код был также закоммичен и опубликован на общедоступном удалённом репозитории, поэтому теперь *Ваш* код базируется на *устаревшей* версии проект и более не уместен.",
+ "",
+ "В этому случае использование комманды `git push` является сомнительным. Как поведёт себя комманда `git push` если Вы её выполните ? Может быть она изменит удалённый репозиторий и вернёт всё к тому состоянию, которое было в понедельник ? А может быть комманда попробует добавить Ваш код, не удаляя при этом новый? Или же она проигнорирует Ваши изменения, так как они уже устарели?",
+ "",
+ "По причине того, что в данной ситуации (когда история расходится) слишком много двусмысленностей и неопределённостей, git не даст Вам закачать (`push`) Ваши изменения. Чтобы поделится и закачать свои наработки, git будет принуждать Вас включить в состав своей работы все те последние наработки и изменения, находящиеся на удалённом репозитории."
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Слишком много болтавни! Давайте посмотрим, как всё работает на живом примере"
+ ],
+ "afterMarkdowns": [
+ "Видите? Ничего не произошло. Всё потому, что комманда `git push` не выполнилась успешно. Дело в том, что Ваш последний коммит `C3` основан на удалённом коммите `C1`. В свою очередь удалённый репозиторий уже изменился под воздействием `C2`. Вот почему git отклонил Ваш push."
+ ],
+ "command": "git push",
+ "beforeCommand": "git clone; git fakeTeamwork; git commit"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Как же разрешит данную ситуацию? Всё очень просто! Всё что Вам нужно - перебазировать свою работу на наиболее последнюю версию удалённой ветки.",
+ "",
+ "Существует множество путей, как сделать это, но наиболее простой способ 'сдвинуть' свои наработки - через пребазировку или rebasing. Давайте посмотрим, как это выглядит."
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Теперь, когда мы сперва перебазиуемся прежде чем публиковать изменения..."
+ ],
+ "afterMarkdowns": [
+ "Опа! Мы только что обновили наш локальный образ удалённого репозитория средствами `git fetch`. Ещё мы перебазировали наши наработки, чтобы они отражали все изменения с удалённого репозитория, и опубликовали их с помощью `git push`"
+ ],
+ "command": "git fetch; git rebase o/master; git push",
+ "beforeCommand": "git clone; git fakeTeamwork; git commit"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "А есть ещё какие-либо варианты чтобы обновить мои наработки, к тому моменту как удалённый репозиторий был обновлён? Конечно есть! Давайте ознакомимся с парочкой новых штучек, но в этот раз с помощью комманды `merge`.",
+ "",
+ "Не смотря на то, что `git merge` не передвигает ваши наработки (а всего лишь создаёт новый коммит, в котором Ваши и удалённые изменения объеденены), этот способ помогает указать git-у на то, что Вы собираетесь включить в состав Ваших наработок все изменения с удалённого репозитория. Это значит, что Ваш коммит отразится на всех коммитах удалённой ветки, поскольку удалённая ветка является *предком* Вашей собственной локальной ветки.",
+ "",
+ "Давайте взглянем на демонстрацию..."
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Таким образм если мы объеденим (merge) вместо перебазирования (rebase)..."
+ ],
+ "afterMarkdowns": [
+ "Опа! Мы обновили наше локальное представление удалённого репозитория с помощью `git fetch`, *объединили* Ваши новые наработки с нашими наработками (чтобы отразить изменения в удалённом репозитории), и затем опубликовали их с помощью `git push`"
+ ],
+ "command": "git fetch; git merge o/master; git push",
+ "beforeCommand": "git clone; git fakeTeamwork; git commit"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Здорово! А можно ли как-то зделать всё тоже самое, но с меньшим количеством комманд?",
+ "",
+ "Конечно -- ведь Вы уже знаете комманду `git pull`, которая является аналогом и более кратким аналогом для совместных fetch и merge. А команда `git pull --rebase` - аналог для совместно вызванных fetch и rebase!",
+ "",
+ "Давайте взглянем на эти оба варианта."
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Сперва - с флагом `--rebase`..."
+ ],
+ "afterMarkdowns": [
+ "Тот же результат как и ранее, но намного короче вызов команд."
+ ],
+ "command": "git pull --rebase; git push",
+ "beforeCommand": "git clone; git fakeTeamwork; git commit"
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "А теперь с обычным `pull`"
+ ],
+ "afterMarkdowns": [
+ "И снова - результат такой же, как и ранее!"
+ ],
+ "command": "git pull; git push",
+ "beforeCommand": "git clone; git fakeTeamwork; git commit"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Рабочий процесс получения изменений (fetching), перебазирования/объединения (rebase/merging) и публикации изменений (pushing) довольно часто используемый. В последующий уроках мы изучим более сложные варианты этих рабочих процессов, но пока что, давайте остановимся на том, что есть.",
+ "",
+ "Выполните следующее, чтобы выполнить задание уровня:",
+ "",
+ "* Склонируйте репозиторий",
+ "* Сфабрикуйте командную работу (1 коммит)",
+ "* Сделайте свой собственный коммит (1 commit)",
+ "* Опубликуйте свои наработки посредствам *перебазировки rebasing*"
+ ]
+ }
+ }
+ ]
}
}
};
diff --git a/src/levels/remote/pull.js b/src/levels/remote/pull.js
index 121d0d69..1aa99a09 100644
--- a/src/levels/remote/pull.js
+++ b/src/levels/remote/pull.js
@@ -10,7 +10,8 @@ exports.level = {
"pt_BR": "Git Pull",
"de_DE": "Git Pull",
"ja" : "Git Pull",
- "fr_FR": "Git pull"
+ "fr_FR": "Git pull",
+ "ru_RU": "Git pull"
},
"hint": {
"en_US": "Just run git pull!",
@@ -20,7 +21,8 @@ exports.level = {
"pt_BR": "Basta executar git pull!",
"de_DE": "Führe einfach git pull aus.",
"ja" : "単にgit pullを実行!",
- "fr_FR": "Utilisez facilement git pull !"
+ "fr_FR": "Utilisez facilement git pull !",
+ "ru_RU": "Запустите комманду git pull !"
},
"startDialog": {
"en_US": {
@@ -435,6 +437,65 @@ exports.level = {
}
}
]
- }
+ },
+ "ru_RU": {
+ "childViews": [
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "## Git Pull",
+ "",
+ "Теперь, когда мы познакомились с тем, как извлекать данные из удалённого репозитория с помощью `git fetch`, давайте обновим нашу работу чтобы отобразить все эти изменения!",
+ "",
+ "Существует множество вариантов решений -- как только у вас имеется локальный коммит, Вы можете соединить его с другой веткой. Это значит Вы можете выполнить одну из комманд:",
+ "",
+ "* `git cherry-pick o/master`",
+ "* `git rebase o/master`",
+ "* `git merge o/master`",
+ "* и т.д.",
+ "",
+ "По факту процедура *скачивания (fetching)* изменений с удалённой ветки и *объединения (merging)* настолько частая и распространённая, что git предоставляет вместо двух команд - одну! Эта команда - `git pull`."
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Давайте рассмотрим, как `fetch` и `merge` выполняются последовательно"
+ ],
+ "afterMarkdowns": [
+ "Опа -- мы скачали `C3` с помощью команды `fetch` и затем объединяем эти наработки с помощью `git merge o/master`. Теперь наша ветка `master` отображает изменения с удалённого репозитория (в данном случае с репозитория `origin`)"
+ ],
+ "command": "git fetch; git merge o/master",
+ "beforeCommand": "git clone; git commit; git fakeTeamwork"
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Что же произойдёт если вместо этих команд мы воспользуемся `git pull` ?"
+ ],
+ "afterMarkdowns": [
+ "Абсолютно тоже самое! Нужно ясно и чётко понимать, что `git pull` существенно уменьшает Вашу рутинную работу, если бы Вы использовали `git fetch` и последующее слияние (merging) скаченной ветки."
+ ],
+ "command": "git pull",
+ "beforeCommand": "git clone; git commit; git fakeTeamwork"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Мы изучим детали комманды `git pull` чуть позже (включая опции и аргументы вызова команды), а пока что давайте просто попробуем эту комманду.",
+ "",
+ "Помните -- мы также можете выполнить этот уровень с помощью комманд `fetch` и `merge`, но нужно ли делать так, когда можно воспользоваться всего-лишь одной коммандой ? :P"
+ ]
+ }
+ }
+ ]
+ }
}
};
diff --git a/src/levels/remote/push.js b/src/levels/remote/push.js
index 3e035955..e26e8aac 100644
--- a/src/levels/remote/push.js
+++ b/src/levels/remote/push.js
@@ -10,7 +10,8 @@ exports.level = {
"pt_BR": "Git Push",
"de_DE": "Git Push",
"ja" : "Git Push",
- "fr_FR": "Git push"
+ "fr_FR": "Git push",
+ "ru_RU": "Git push"
},
"hint": {
"en_US": "Remember you have to clone before you can push!",
@@ -20,7 +21,8 @@ exports.level = {
"pt_BR": "Lembre-se de clonar antes de fazer o push!",
"de_DE": "Denk dran, dass du einen Clone brauchst bevor du Pushen kannst!",
"ja" : "Pushできる前にまずリポジトリをcloneする必要があるのをお忘れなく",
- "fr_FR": "Rappelez-vous que vous devez cloner avant de pouvoir faire un push !"
+ "fr_FR": "Rappelez-vous que vous devez cloner avant de pouvoir faire un push !",
+ "ru_RU": "Помните, что прежде чем push-ить вам нужно сколнировать репозиторий!"
},
"startDialog": {
"en_US": {
@@ -315,6 +317,49 @@ exports.level = {
}
}
]
+ },
+ "ru_RU": {
+ "childViews": [
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "## Git Push",
+ "",
+ "Хорошо, мы скачали изменения с удалённого репозитория и включили их в наши локальные наработки. Всё это замечательно, но, как нам поделиться _своими_ наработками и изменениями с другими участниками проекта?",
+ "",
+ "Способ, которым мы воспользуемся, является противоположным тому способу, которым мы пользовались ранее для скачивания наработок (`git pull`). Этот способ - использование комманды `git push`!",
+ "",
+ "Комманда `git push` отвечает за загрузку _Ваших_ изменений в указанный удалённый репозиторий, а также включение Ваших коммитов в состав удалённого репозитория. По окончанию работы комманды `git push` все Ваши друзья смогут скачать себе все сделанные Вами наработки.",
+ "",
+ "Вы можете рассматривать комманду `git push` как \"публикацию\" своей работы. Эта комманда скрывает в себе множество тонкостей и ньюансов, с которыми мы познакомимся в ближайшее время, а пока что давайте начнём с малого...",
+ "",
+ "*замечание -- поведение комманды `git push` без аргументов варьируется в зависимости он значения `push.default`,указанной в настройках git-а. Значение по-умолчанию зависит от версии git, которую Вы используете, однако в наших уроках мы будем использовать значение `upstream`. Лучше всегда проверят эту опцию прежде чем push-ить Ваши настоящие проекты.*"
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Здесь у нас имеются изменения, которых нету в удалённом репозитории. Давайте же закачаем их туда!"
+ ],
+ "afterMarkdowns": [
+ "Вот так -- удалённый репозиторий получил новый коммит `C2`, ветка `master` на удалённом репозитории теперь указывает на `C2`, и наше *собственное* локальное отображение удалённого репозитория (`o/master`) изменилось соответственно. Всё синхронизировалось!"
+ ],
+ "command": "git push",
+ "beforeCommand": "git clone; git commit"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Чтобы выполнить задачу этого упражнения, просто поделитесь своими двумя новыми коммитами с удалённым репозиторием. Соберитесь, потому что все последующие уроки будут намного сложнее предыдущих!"
+ ]
+ }
+ }
+ ]
}
}
};
diff --git a/src/levels/remote/pushArgs.js b/src/levels/remote/pushArgs.js
index 58fb68e7..002bf106 100644
--- a/src/levels/remote/pushArgs.js
+++ b/src/levels/remote/pushArgs.js
@@ -92,7 +92,10 @@ exports.level = {
"type": "ModalAlert",
"options": {
"markdowns": [
- "Ok, for this level let's update both `foo` and `master` on the remote. The twist is that `git checkout` is disabled for this level!"
+ "Ok, for this level let's update both `foo` and `master` on the remote. The twist is that `git checkout` is disabled for this level!",
+ "",
+ "*Note: The remote branches are labeled with `o/` prefixes because the full `origin/` label does not fit in our UI. Don't worry ",
+ "about this... simply use `origin` as the name of the remote like normal.*"
]
}
}
diff --git a/src/levels/remote/pushManyFeatures.js b/src/levels/remote/pushManyFeatures.js
index d10abd43..6f2b0a72 100644
--- a/src/levels/remote/pushManyFeatures.js
+++ b/src/levels/remote/pushManyFeatures.js
@@ -10,7 +10,8 @@ exports.level = {
"pt_BR": "Lembre-se que você sempre pode usar undo ou reset",
"de_DE": "Denk dran, du kannst immer undo oder reset benutzen, um deine Befehle zurück zu nehmen.",
"ja" : "undoやresetコマンドをいつでも使用することができるのをお忘れなく",
- "fr_FR": "Rappelez-vous que vous pouvez toujours utiliser les commandes undo et reset."
+ "fr_FR": "Rappelez-vous que vous pouvez toujours utiliser les commandes undo et reset.",
+ "ru_RU": "Помни - ты всегда можешь отменить комманды с помощью undo или reset"
},
"name": {
"en_US": "Push Master!",
@@ -20,7 +21,8 @@ exports.level = {
"pt_BR": "Push Master!",
"de_DE": "Push Master!",
"ja": "Push Master!",
- "fr_FR": "Maître du push !"
+ "fr_FR": "Maître du push !",
+ "ru_RU": "Push Мастер!"
},
"compareOnlyMasterHashAgnostic": true,
"startDialog": {
@@ -394,6 +396,59 @@ exports.level = {
}
}
]
+ },
+ "ru_RU": {
+ "childViews": [
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "## Слияние фича-бранчей (веток)",
+ "",
+ "Теперь, когда Вы умело владеете коммандами fetch, pull и push давайте применим эти навыки в сочетании с новым рабочим процессом (он же workflow).",
+ "",
+ "Для разработчиков, вовлечённых в большой проект, является довольно распространённым выполнять всё свою работу на так называемых фича-бранчах (вне `master`). А затем, как только работа выполнена, разработчик интегрирует всё что было им сделано. Всё это, за исключением одного шага, довольно похоже на предыдущий урок (там, где мы закачивали ветки на удалённый репозиторий)",
+ "",
+ "Ряд разработчиков делают push и pull лишь на локальную ветку `master` -- таким образом ветка `master` всегда обновлена с тем, что находится на удалённом репозитории (`o/master`).",
+ "",
+ "Для этого рабочего процесса мы совместили две вещи:",
+ "",
+ "* интеграция фича-бранчей в `master`, а также ",
+ "* закачку (push) и скачку (pull) с удалённого репозитория"
+ ]
+ }
+ },
+ {
+ "type": "GitDemonstrationView",
+ "options": {
+ "beforeMarkdowns": [
+ "Давайте быстренько вспомним, как нам обновить `master` и закачать выполненную работу."
+ ],
+ "afterMarkdowns": [
+ "Здесь мы выполнили две комманды, которые:",
+ "",
+ "* перебазировали нашу работу на новенький коммит, пришедший с удалённого репозитория, и",
+ "* закачали свои наработки в удалённый репозиторий"
+ ],
+ "command": "git pull --rebase; git push",
+ "beforeCommand": "git clone; git commit; git fakeTeamwork"
+ }
+ },
+ {
+ "type": "ModalAlert",
+ "options": {
+ "markdowns": [
+ "Текущая задача является достаточно обильной -- здесь представлена общая схема выполнения:",
+ "",
+ "* Есть три фича-бранчи (фича-ветки) -- `side1` `side2` и `side3`",
+ "* Нам необходимо закачать каждую из них по очереди на удалённый репозиторий",
+ "* При этом удалённый репозиторий хранит в себе какие-то наработки, которые также следует скачать к себе",
+ "",
+ ":O Сложно! Желаю Вам удачи в выполнении этой непростой задачи."
+ ]
+ }
+ }
+ ]
}
}
};
diff --git a/src/style/main.css b/src/style/main.css
index 18da8cba..d6d283d7 100644
--- a/src/style/main.css
+++ b/src/style/main.css
@@ -865,6 +865,7 @@ div.displayName h3 {
div.iconHolder {
}
+div.seriesView p.levelInfo,
div.seriesView p.about {
margin: 0px;
padding: 4px;
@@ -872,6 +873,10 @@ div.seriesView p.about {
color: #CCC;
}
+div.seriesView p.levelInfo {
+ font-style: italic;
+}
+
div.levelIcon {
height: 40px;
width: 40px;
diff --git a/src/template.index.html b/src/template.index.html
index 4c8458e6..f33306f0 100644
--- a/src/template.index.html
+++ b/src/template.index.html
@@ -222,6 +222,9 @@
<%= about %>
+ <%= levelInfo %>
+