mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-26 07:58:34 +02:00
add zh-tw
This commit is contained in:
commit
c9e180393d
66 changed files with 4341 additions and 325 deletions
|
@ -79,40 +79,15 @@ module.exports = function(grunt) {
|
||||||
});
|
});
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
lint: {
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
files: ['grunt.js', 'src/**/*.js', 'spec/*.js']
|
|
||||||
},
|
|
||||||
compliment: {
|
|
||||||
compliments: [
|
|
||||||
"Wow peter great work!",
|
|
||||||
"Such a professional dev environment",
|
|
||||||
"Can't stop the TRAIN",
|
|
||||||
"git raging"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
hash: {
|
|
||||||
src: ['build/bundle.min.js', 'src/style/main.css'],
|
|
||||||
dest: 'build/'
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
files: '<config:lint.files>',
|
|
||||||
tasks: 'watching'
|
|
||||||
},
|
|
||||||
min: {
|
|
||||||
dist: {
|
|
||||||
src: ['build/bundle.js'],
|
|
||||||
dest: 'build/bundle.min.js'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rm: {
|
|
||||||
build: 'build/*'
|
|
||||||
},
|
|
||||||
shell: {
|
|
||||||
gitAdd: {
|
|
||||||
command: 'git add build/'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
jshint: {
|
jshint: {
|
||||||
|
all: [
|
||||||
|
'Gruntfile.js',
|
||||||
|
'spec/*.js',
|
||||||
|
'src/js/**/*.js',
|
||||||
|
'src/js/**/**/*.js',
|
||||||
|
'src/levels/**/*.js',
|
||||||
|
],
|
||||||
options: {
|
options: {
|
||||||
curly: true,
|
curly: true,
|
||||||
// sometimes triple equality is just redundant and unnecessary
|
// sometimes triple equality is just redundant and unnecessary
|
||||||
|
@ -142,8 +117,7 @@ module.exports = function(grunt) {
|
||||||
boss: true,
|
boss: true,
|
||||||
eqnull: true,
|
eqnull: true,
|
||||||
browser: true,
|
browser: true,
|
||||||
debug: true
|
debug: true,
|
||||||
},
|
|
||||||
globals: {
|
globals: {
|
||||||
Raphael: true,
|
Raphael: true,
|
||||||
require: true,
|
require: true,
|
||||||
|
@ -159,6 +133,41 @@ module.exports = function(grunt) {
|
||||||
process: true
|
process: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
compliment: {
|
||||||
|
compliments: [
|
||||||
|
"Wow peter great work!",
|
||||||
|
"Such a professional dev environment",
|
||||||
|
"Can't stop the TRAIN",
|
||||||
|
"git raging"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
hash: {
|
||||||
|
js: {
|
||||||
|
src: 'build/bundle.min.js',
|
||||||
|
dest: 'build/'
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
src: 'src/style/main.css',
|
||||||
|
dest: 'build/'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
files: '<config:lint.files>',
|
||||||
|
tasks: 'watching'
|
||||||
|
},
|
||||||
|
uglify: {
|
||||||
|
build: {
|
||||||
|
src: ['build/bundle.js'],
|
||||||
|
dest: 'build/bundle.min.js'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clean: ['build/*'],
|
||||||
|
shell: {
|
||||||
|
gitAdd: {
|
||||||
|
command: 'git add build/'
|
||||||
|
}
|
||||||
|
},
|
||||||
jasmine_node: {
|
jasmine_node: {
|
||||||
specNameMatcher: 'spec',
|
specNameMatcher: 'spec',
|
||||||
projectRoot: '.',
|
projectRoot: '.',
|
||||||
|
@ -167,26 +176,31 @@ module.exports = function(grunt) {
|
||||||
requirejs: false
|
requirejs: false
|
||||||
},
|
},
|
||||||
browserify: {
|
browserify: {
|
||||||
'build/bundle.js': {
|
dist: {
|
||||||
entries: ['src/**/*.js', 'src/js/**/*.js']
|
files: {
|
||||||
//prepend: ['<banner:meta.banner>'],
|
'build/bundle.js': ['src/**/*.js', 'src/js/**/*.js'],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// all my npm helpers
|
// all my npm helpers
|
||||||
grunt.loadNpmTasks('grunt-jslint');
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
grunt.loadNpmTasks('grunt-browserify');
|
grunt.loadNpmTasks('grunt-browserify');
|
||||||
grunt.loadNpmTasks('grunt-hash');
|
grunt.loadNpmTasks('grunt-hash');
|
||||||
grunt.loadNpmTasks('grunt-rm');
|
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||||
grunt.loadNpmTasks('grunt-shell');
|
grunt.loadNpmTasks('grunt-shell-spawn');
|
||||||
grunt.loadNpmTasks('grunt-jasmine-node');
|
grunt.loadNpmTasks('grunt-jasmine-node');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
|
||||||
grunt.registerTask('build', 'rm browserify min hash buildIndex shell jasmine_node lint lintStrings compliment');
|
grunt.registerTask('build',
|
||||||
grunt.registerTask('fastBuild', 'rm browserify hash buildIndex');
|
['clean', 'browserify', 'uglify', 'hash', 'buildIndex', 'shell', 'jasmine_node', 'jshint', 'lintStrings', 'compliment']
|
||||||
grunt.registerTask('watching', 'fastBuild jasmine_node lint lintStrings');
|
);
|
||||||
|
grunt.registerTask('lint', ['jshint', 'compliment']);
|
||||||
|
grunt.registerTask('fastBuild', ['clean', 'browserify', 'hash', 'buildIndex', 'jshint']);
|
||||||
|
grunt.registerTask('watching', ['fastBuild', 'jasmine_node', 'jshint', 'lintStrings']);
|
||||||
|
|
||||||
grunt.registerTask('default', 'build');
|
grunt.registerTask('default', ['build']);
|
||||||
grunt.registerTask('test', 'jasmine_node');
|
grunt.registerTask('test', ['jasmine_node']);
|
||||||
};
|
};
|
||||||
|
|
33
README.md
33
README.md
|
@ -3,6 +3,8 @@
|
||||||
LearnGitBranching is a git repository visualizer, sandbox, and series of educational tutorials and challenges. Its primary purpose is to help developers understand git through the power of visualization (something that's absent when working on the command line).
|
LearnGitBranching is a git repository visualizer, sandbox, and series of educational tutorials and challenges. Its primary purpose is to help developers understand git through the power of visualization (something that's absent when working on the command line).
|
||||||
|
|
||||||
You can input a variety of commands into LearnGitBranching (LGB) -- as commands are processed, the nearby commit tree will dynamically update to reflect the effects of each command:
|
You can input a variety of commands into LearnGitBranching (LGB) -- as commands are processed, the nearby commit tree will dynamically update to reflect the effects of each command:
|
||||||
|
|
||||||
|
|
||||||
<img src="https://raw.github.com/pcottle/learnGitBranching/master/assets/learnGitBranching.png"/>
|
<img src="https://raw.github.com/pcottle/learnGitBranching/master/assets/learnGitBranching.png"/>
|
||||||
|
|
||||||
This visualization combined with tutorials and "levels" can help both beginners and intermediate developers polish their version control skills. A quick demo is available here:
|
This visualization combined with tutorials and "levels" can help both beginners and intermediate developers polish their version control skills. A quick demo is available here:
|
||||||
|
@ -37,6 +39,8 @@ LearnGitBranching is a pretty simple application (from a technical perspective).
|
||||||
|
|
||||||
Because the app contains a lot of code, I have written everything into Nodejs-style modules. The modules are packaged together with the `Browserify` and then sent down in a format the browser can understand.
|
Because the app contains a lot of code, I have written everything into Nodejs-style modules. The modules are packaged together with the `Browserify` and then sent down in a format the browser can understand.
|
||||||
|
|
||||||
|
As of December 2013, I've migrated the build process to use Grunt >0.4, since the older version was giving a lot of people build headaches. It should be fairly rock solid now!
|
||||||
|
|
||||||
Here is the high level process of the build:
|
Here is the high level process of the build:
|
||||||
|
|
||||||
* Code is written into the node.js modules which require other modules
|
* Code is written into the node.js modules which require other modules
|
||||||
|
@ -55,8 +59,9 @@ Thus, if you build the app locally, all you have to do in order to run the app i
|
||||||
## Building yourself / Contributing Functionality
|
## Building yourself / Contributing Functionality
|
||||||
|
|
||||||
For contributing core functionality in the app, you'll probably want to test your changes
|
For contributing core functionality in the app, you'll probably want to test your changes
|
||||||
at least once before submitting a pull request. That means you'll need the `grunt` build tool. It's a fairly
|
at least once before submitting a pull request. That means you'll need the "Grunt.js" build tool to build the app:
|
||||||
common tool, however I use a slightly older version.
|
|
||||||
|
http://gruntjs.com/getting-started
|
||||||
|
|
||||||
You'll also need `npm` to download all the dependencies of the project.
|
You'll also need `npm` to download all the dependencies of the project.
|
||||||
|
|
||||||
|
@ -66,13 +71,17 @@ The general workflow / steps are below:
|
||||||
git clone <your fork of the repo>
|
git clone <your fork of the repo>
|
||||||
cd learnGitBranching
|
cd learnGitBranching
|
||||||
npm install # to install all the node modules I depend on
|
npm install # to install all the node modules I depend on
|
||||||
|
|
||||||
git checkout -b newAwesomeFeature
|
git checkout -b newAwesomeFeature
|
||||||
# some changes
|
vim ./src/js/git/index.js # some changes
|
||||||
./node_modules/grunt/bin/grunt fastBuild # to use the npm version of grunt
|
grunt fastBuild # skips tests and linting, faster build
|
||||||
# after building you can open up your browser to the index.html that is generated and see your changes
|
|
||||||
grunt watch # will keep watch over files and fastBuild whenever they change. lot of CPU though
|
# after building you can open up your browser to the index.html
|
||||||
# more changes
|
# file generated and see your changes
|
||||||
./node_modules/grunt/bin/grunt build # build runs the tests and lint as well
|
|
||||||
|
vim ./src/js/git/index.js # more changes
|
||||||
|
grunt build # runs tests and lint
|
||||||
|
|
||||||
git commit -am "My new sweet feature!"
|
git commit -am "My new sweet feature!"
|
||||||
git push
|
git push
|
||||||
# go online and request a pull
|
# go online and request a pull
|
||||||
|
@ -92,9 +101,12 @@ And the following heroes for assisting in translating:
|
||||||
* "scientific-coder"
|
* "scientific-coder"
|
||||||
* "ace-coder"
|
* "ace-coder"
|
||||||
* Joël Thieffry
|
* Joël Thieffry
|
||||||
|
* Jens Bremmekamp ("nem75")
|
||||||
|
* "hilojack"
|
||||||
|
|
||||||
Also huge shoutout for everyone who has put up a pull request that was pulled:
|
Also huge shoutout for everyone who has put up a pull request that was pulled:
|
||||||
|
|
||||||
|
* Sergey Krilov -- Draggable windows!
|
||||||
* Aaron Schrab - 5x!!
|
* Aaron Schrab - 5x!!
|
||||||
* Stephen Cavaliere
|
* Stephen Cavaliere
|
||||||
* Andrew Ardill
|
* Andrew Ardill
|
||||||
|
@ -114,11 +126,12 @@ Also huge shoutout for everyone who has put up a pull request that was pulled:
|
||||||
* Allen Guo
|
* Allen Guo
|
||||||
* Timothy Qiu
|
* Timothy Qiu
|
||||||
* Hyunjin CHA
|
* Hyunjin CHA
|
||||||
* "nem75"
|
* Jens Bremmekamp ("nem75")
|
||||||
* Fabio Crisci (piuccio)
|
* Fabio Crisci (piuccio)
|
||||||
* Max Sikström (pengi) [tag support!!]
|
* Max Sikström (pengi) [tag support!!]
|
||||||
* "rogererens"
|
* "rogererens"
|
||||||
* Emanuel Schorsch
|
* Emanuel Schorsch
|
||||||
|
* Carl X. Su
|
||||||
|
|
||||||
Or reported an issue that was successfully closed!
|
Or reported an issue that was successfully closed!
|
||||||
|
|
||||||
|
@ -156,4 +169,6 @@ Or reported an issue that was successfully closed!
|
||||||
* "iplus"
|
* "iplus"
|
||||||
* Christian Sauer
|
* Christian Sauer
|
||||||
* "alvarogarcia7"
|
* "alvarogarcia7"
|
||||||
|
* Il Memming Park
|
||||||
|
* Neil Traft
|
||||||
|
|
||||||
|
|
27
package.json
27
package.json
|
@ -1,23 +1,26 @@
|
||||||
{
|
{
|
||||||
"name": "LearnGitBranching",
|
"name": "LearnGitBranching",
|
||||||
"version": "0.5.0",
|
"version": "0.8.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"grunt": "~0.3.17",
|
"grunt": "~0.4.2",
|
||||||
"jasmine-node": "~1.11.0",
|
"jasmine-node": "~1.12.0",
|
||||||
"grunt-browserify": "0.1.1",
|
"grunt-browserify": "~1.3.0",
|
||||||
"grunt-jslint": "~0.2.2-1",
|
"grunt-jasmine-node": "~0.1.0",
|
||||||
"grunt-jasmine-node": "0.1.0",
|
"grunt-hash": "~0.5.0",
|
||||||
"grunt-hash": "0.2.2",
|
"prompt": "0.2.9",
|
||||||
"grunt-rm": "~0.0.3",
|
"browserify": "~3.14.1",
|
||||||
"grunt-shell": "0.1.4",
|
"grunt-cli": "~0.1.11",
|
||||||
"prompt": "0.2.9"
|
"grunt-contrib-uglify": "~0.2.7",
|
||||||
|
"grunt-contrib-jshint": "~0.7.2",
|
||||||
|
"grunt-contrib-clean": "~0.5.0",
|
||||||
|
"grunt-lib-phantomjs": "~0.4.0",
|
||||||
|
"grunt-shell-spawn": "~0.3.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"backbone": "~0.9.9",
|
"backbone": "~0.9.9",
|
||||||
"underscore": "~1.4.3",
|
"underscore": "~1.4.3",
|
||||||
"jquery": "~1.7.3",
|
"jquery": "~1.7.3",
|
||||||
"q": "~0.8.11",
|
"q": "~0.8.11",
|
||||||
"markdown": "~0.4.0",
|
"markdown": "~0.4.0"
|
||||||
"grunt-shell": "~0.1.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
spec/base.js
10
spec/base.js
|
@ -6,7 +6,7 @@ var loadTree = function(json) {
|
||||||
};
|
};
|
||||||
|
|
||||||
var compareLevelTree = function(headless, levelBlob) {
|
var compareLevelTree = function(headless, levelBlob) {
|
||||||
var actualTree = headless.gitEngine.exportTree();
|
var actualTree = headless.gitEngine.printTree();
|
||||||
return TreeCompare.dispatchFromLevel(levelBlob, actualTree);
|
return TreeCompare.dispatchFromLevel(levelBlob, actualTree);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ var expectLevelAsync = function(headless, levelBlob) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasWarned = false;
|
||||||
var start;
|
var start;
|
||||||
runs(function() {
|
runs(function() {
|
||||||
start = Date.now();
|
start = Date.now();
|
||||||
|
@ -37,8 +38,11 @@ var expectLevelAsync = function(headless, levelBlob) {
|
||||||
});
|
});
|
||||||
waitsFor(function() {
|
waitsFor(function() {
|
||||||
var diff = (Date.now() - start);
|
var diff = (Date.now() - start);
|
||||||
if (diff > TIME - 10) {
|
if (diff > TIME - 10 && !hasWarned) {
|
||||||
console.log('not going to match', command);
|
hasWarned = true;
|
||||||
|
console.log('this goal tree', loadTree(levelBlob.goalTreeString));
|
||||||
|
console.log('not going to match with command', command);
|
||||||
|
console.log(getHeadlessSummary(headless));
|
||||||
}
|
}
|
||||||
var result = compareLevelTree(headless, levelBlob);
|
var result = compareLevelTree(headless, levelBlob);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
|
|
@ -6,7 +6,8 @@ describe('GitEngine Levels', function() {
|
||||||
var sequences = require('../src/levels/index').levelSequences;
|
var sequences = require('../src/levels/index').levelSequences;
|
||||||
_.each(Object.keys(sequences), function(sequenceKey) {
|
_.each(Object.keys(sequences), function(sequenceKey) {
|
||||||
var levels = sequences[sequenceKey];
|
var levels = sequences[sequenceKey];
|
||||||
_.each(levels, function(levelBlob) {
|
_.each(levels, function(levelBlob, index) {
|
||||||
|
console.log('testing level', levelBlob.name.en_US);
|
||||||
base.expectLevelSolved(levelBlob);
|
base.expectLevelSolved(levelBlob);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -346,5 +346,33 @@ describe('Git Remotes', function() {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not fetch if one arg is not branch ref', function() {
|
||||||
|
expectTreeAsync(
|
||||||
|
'git clone; git fakeTeamwork 2; git fetch origin master~1',
|
||||||
|
'{"branches":{"master":{"target":"C1","id":"master","remoteTrackingBranchID":"o/master"},"o/master":{"target":"C1","id":"o/master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"tags":{},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"target":"C3","id":"master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"tags":{},"HEAD":{"target":"master","id":"HEAD"}}}'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates the branch on the fly', function() {
|
||||||
|
expectTreeAsync(
|
||||||
|
'git clone; git commit; go -b side; git push origin side',
|
||||||
|
'{"branches":{"master":{"target":"C2","id":"master","remoteTrackingBranchID":"o/master"},"o/master":{"target":"C1","id":"o/master","remoteTrackingBranchID":null},"side":{"target":"C2","id":"side","remoteTrackingBranchID":"o/side"},"o/side":{"target":"C2","id":"o/side","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"tags":{},"HEAD":{"target":"side","id":"HEAD"},"originTree":{"branches":{"master":{"target":"C1","id":"master","remoteTrackingBranchID":null},"side":{"target":"C2","id":"side","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"tags":{},"HEAD":{"target":"master","id":"HEAD"}}}'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not create the o/master branch on remote', function() {
|
||||||
|
expectTreeAsync(
|
||||||
|
'git clone; git commit; git push origin o/master',
|
||||||
|
'{"branches":{"master":{"target":"C2","id":"master","remoteTrackingBranchID":"o/master"},"o/master":{"target":"C1","id":"o/master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"}},"tags":{},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"target":"C1","id":"master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"tags":{},"HEAD":{"target":"master","id":"HEAD"}}}'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pulls with rebase correctly in weird situation with no rebase to do', function() {
|
||||||
|
expectTreeAsync(
|
||||||
|
'git checkout -b side; git commit; git checkout master; git commit; git commit; git merge side; git commit; git clone; git checkout -b main master^^^; git rebase side; git rebase main master; git push;git pull --rebase',
|
||||||
|
'%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C6%22%2C%22id%22%3A%22master%22%2C%22remoteTrackingBranchID%22%3A%22o/master%22%7D%2C%22side%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22side%22%2C%22remoteTrackingBranchID%22%3A%22o/side%22%7D%2C%22o/master%22%3A%7B%22target%22%3A%22C6%22%2C%22id%22%3A%22o/master%22%2C%22remoteTrackingBranchID%22%3Anull%7D%2C%22o/side%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22o/side%22%2C%22remoteTrackingBranchID%22%3Anull%7D%2C%22main%22%3A%7B%22target%22%3A%22C3%27%22%2C%22id%22%3A%22main%22%2C%22remoteTrackingBranchID%22%3Anull%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C2%22%2C%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%2C%22C3%27%22%3A%7B%22parents%22%3A%5B%22C2%22%5D%2C%22id%22%3A%22C3%27%22%7D%2C%22C4%27%22%3A%7B%22parents%22%3A%5B%22C3%27%22%5D%2C%22id%22%3A%22C4%27%22%7D%2C%22C6%27%22%3A%7B%22parents%22%3A%5B%22C4%27%22%5D%2C%22id%22%3A%22C6%27%22%7D%7D%2C%22tags%22%3A%7B%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%2C%22originTree%22%3A%7B%22branches%22%3A%7B%22master%22%3A%7B%22target%22%3A%22C6%22%2C%22id%22%3A%22master%22%2C%22remoteTrackingBranchID%22%3Anull%7D%2C%22side%22%3A%7B%22target%22%3A%22C2%22%2C%22id%22%3A%22side%22%2C%22remoteTrackingBranchID%22%3Anull%7D%7D%2C%22commits%22%3A%7B%22C0%22%3A%7B%22parents%22%3A%5B%5D%2C%22id%22%3A%22C0%22%2C%22rootCommit%22%3Atrue%7D%2C%22C1%22%3A%7B%22parents%22%3A%5B%22C0%22%5D%2C%22id%22%3A%22C1%22%7D%2C%22C2%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C2%22%7D%2C%22C3%22%3A%7B%22parents%22%3A%5B%22C1%22%5D%2C%22id%22%3A%22C3%22%7D%2C%22C4%22%3A%7B%22parents%22%3A%5B%22C3%22%5D%2C%22id%22%3A%22C4%22%7D%2C%22C5%22%3A%7B%22parents%22%3A%5B%22C2%22%2C%22C4%22%5D%2C%22id%22%3A%22C5%22%7D%2C%22C6%22%3A%7B%22parents%22%3A%5B%22C5%22%5D%2C%22id%22%3A%22C6%22%7D%7D%2C%22tags%22%3A%7B%7D%2C%22HEAD%22%3A%7B%22target%22%3A%22master%22%2C%22id%22%3A%22HEAD%22%7D%7D%7D'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ describe('Tree Compare', function() {
|
||||||
// state with originTree
|
// state with originTree
|
||||||
'{"branches":{"master":{"target":"C1","id":"master"},"o/master":{"target":"C1","id":"o/master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"remoteTrackingBranch":null,"remote":false,"target":"C1","id":"master","type":"branch"}},"commits":{"C0":{"type":"commit","parents":[],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 09:58:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C0","rootCommit":true},"C1":{"type":"commit","parents":["C0"],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 09:58:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C1"}},"HEAD":{"target":"master","id":"HEAD","type":"general ref"}}}',
|
'{"branches":{"master":{"target":"C1","id":"master"},"o/master":{"target":"C1","id":"o/master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"remoteTrackingBranch":null,"remote":false,"target":"C1","id":"master","type":"branch"}},"commits":{"C0":{"type":"commit","parents":[],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 09:58:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C0","rootCommit":true},"C1":{"type":"commit","parents":["C0"],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 09:58:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C1"}},"HEAD":{"target":"master","id":"HEAD","type":"general ref"}}}',
|
||||||
{
|
{
|
||||||
|
// different cases for origin tree too
|
||||||
|
'{"branches":{"MaStEr":{"target":"C1","id":"MaStEr"},"o/master":{"target":"C1","id":"o/MaStEr"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"MaStEr","id":"HEAD"},"originTree":{"branches":{"MaStEr":{"remoteTrackingBranch":null,"remote":false,"target":"C1","id":"MaStEr","type":"branch"}},"commits":{"C0":{"type":"commit","parents":[],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 09:58:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C0","rootCommit":true},"C1":{"type":"commit","parents":["C0"],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 09:58:50 GMT-0800 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C1"}},"HEAD":{"target":"MaStEr","id":"HEAD","type":"general ref"}}}': true,
|
||||||
// one extra commit in origin
|
// one extra commit in origin
|
||||||
'{"branches":{"master":{"target":"C1","id":"master"},"o/master":{"target":"C1","id":"o/master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"remoteTrackingBranch":null,"remote":false,"target":"C2","id":"master","type":"branch"}},"commits":{"C0":{"type":"commit","parents":[],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 10:24:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C0","rootCommit":true},"C1":{"type":"commit","parents":["C0"],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 10:24:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C1"},"C2":{"type":"commit","parents":["C1"],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 10:24:55 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C2"}},"HEAD":{"target":"master","id":"HEAD","type":"general ref"}}}': false,
|
'{"branches":{"master":{"target":"C1","id":"master"},"o/master":{"target":"C1","id":"o/master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"remoteTrackingBranch":null,"remote":false,"target":"C2","id":"master","type":"branch"}},"commits":{"C0":{"type":"commit","parents":[],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 10:24:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C0","rootCommit":true},"C1":{"type":"commit","parents":["C0"],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 10:24:50 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C1"},"C2":{"type":"commit","parents":["C1"],"author":"Peter Cottle","createTime":"Wed Jul 24 2013 10:24:55 GMT-0700 (PDT)","commitMessage":"Quick commit. Go Bears!","id":"C2"}},"HEAD":{"target":"master","id":"HEAD","type":"general ref"}}}': false,
|
||||||
// extra commit local
|
// extra commit local
|
||||||
|
@ -88,6 +90,8 @@ describe('Tree Compare', function() {
|
||||||
{
|
{
|
||||||
// side branch that is checked out
|
// side branch that is checked out
|
||||||
'{"branches":{"master":{"target":"C2","id":"master"},"side":{"target":"C3","id":"side"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"side","id":"HEAD"}}': false,
|
'{"branches":{"master":{"target":"C2","id":"master"},"side":{"target":"C3","id":"side"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"side","id":"HEAD"}}': false,
|
||||||
|
// different cases of branches
|
||||||
|
'{"branches":{"mAsTeR":{"target":"C3","id":"mAsTeR"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"mAsTeR","id":"HEAD"}}': true,
|
||||||
// head detached
|
// head detached
|
||||||
'{"branches":{"master":{"target":"C3","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"C2","id":"HEAD"}}': false
|
'{"branches":{"master":{"target":"C3","id":"master"}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"},"C2":{"parents":["C1"],"id":"C2"},"C3":{"parents":["C2"],"id":"C3"}},"HEAD":{"target":"C2","id":"HEAD"}}': false
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ var Backbone = require('backbone');
|
||||||
var constants = require('../util/constants');
|
var constants = require('../util/constants');
|
||||||
var util = require('../util');
|
var util = require('../util');
|
||||||
var intl = require('../intl');
|
var intl = require('../intl');
|
||||||
|
var GlobalState = require('../util/globalState');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globals
|
* Globals
|
||||||
|
@ -195,7 +196,7 @@ var initDemo = function(sandbox) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.locale !== undefined && params.locale.length) {
|
if (params.locale !== undefined && params.locale.length) {
|
||||||
constants.GLOBAL.locale = params.locale;
|
GlobalState.locale = params.locale;
|
||||||
events.trigger('localeChanged');
|
events.trigger('localeChanged');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,16 @@ exports.dialog = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
'de_DE': [{
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Bist du sicher, dass du die Auflösung sehen willst?',
|
||||||
|
'',
|
||||||
|
'Ich glaube an dich! Du schaffst das!'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}],
|
||||||
'zh_CN': [{
|
'zh_CN': [{
|
||||||
type: 'ModalAlert',
|
type: 'ModalAlert',
|
||||||
options: {
|
options: {
|
||||||
|
|
|
@ -18,6 +18,25 @@ exports.dialog = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
'de_DE': [{
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Willkommen zum Level-Editor!',
|
||||||
|
'',
|
||||||
|
'So funktioniert\'s:',
|
||||||
|
'',
|
||||||
|
' * Stelle mit Git-Befehlen die Ausganssituation her',
|
||||||
|
' * Leg den Startpunkt mit ```define start``` fest',
|
||||||
|
' * Gib eine Abfolge von Git-Befehlen ein, welche die (optimale) Lösung darstellen',
|
||||||
|
' * Leg den Ziel-Baum mit ```define goal``` fest. Damit markierst du den Endpunkt der Lösung',
|
||||||
|
' * Gib einen Hinweis mittels ```define hint``` an, wenn du willst',
|
||||||
|
' * Änder den Namen mittels ```define name```',
|
||||||
|
' * Wenn du magst, erstelle einen schönene Einführungsdialog mit ```edit dialog```',
|
||||||
|
' * Gib das Kommando ```finish``` ein um deinen Level als JSON auszugeben'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}],
|
||||||
'zh_CN': [{
|
'zh_CN': [{
|
||||||
type: 'ModalAlert',
|
type: 'ModalAlert',
|
||||||
options: {
|
options: {
|
||||||
|
|
|
@ -10,6 +10,17 @@ exports.dialog = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
'de_DE': [{
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Super gemacht',
|
||||||
|
'',
|
||||||
|
'Du hast den Level in *{numCommands}* Befehl(en) gelöst;',
|
||||||
|
'meine Lösung besteht aus {best}.'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}],
|
||||||
'ja': [{
|
'ja': [{
|
||||||
type: 'ModalAlert',
|
type: 'ModalAlert',
|
||||||
options: {
|
options: {
|
||||||
|
|
|
@ -55,6 +55,59 @@ exports.dialog = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
'de_DE': [{
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Willkommen bei LearnGitBranching!',
|
||||||
|
'',
|
||||||
|
'Der Sinn dieser Anwendung ist, die umfangreichen und komplexen Zusammenhänge der Prozesse, die bei der Arbeit mit Git ablaufen, zu verdeutlichen. Ich hoffe du hast Spaß dabei und lernst vielleicht sogar etwas!',
|
||||||
|
'',
|
||||||
|
'# Demo!',
|
||||||
|
'',
|
||||||
|
'Falls du die Demonstration noch nicht gesehen hast, schau sie dir hier an:',
|
||||||
|
'',
|
||||||
|
'[http://pcottle.github.io/learnGitBranching/?demo](http://pcottle.github.io/learnGitBranching/?demo)',
|
||||||
|
'',
|
||||||
|
'Genervt von diesem Fenster? Häng `?NODEMO` an die URL um es los zu werden, so wie hier:',
|
||||||
|
'',
|
||||||
|
'[http://pcottle.github.io/learnGitBranching/?NODEMO](?NODEMO)'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Git-Kommandos',
|
||||||
|
'',
|
||||||
|
'Dir steht eine große Zahl von Git-Befehlen im Sandkasten-Modus zur Verfügung. Unter anderem',
|
||||||
|
'',
|
||||||
|
' * commit',
|
||||||
|
' * branch',
|
||||||
|
' * checkout',
|
||||||
|
' * cherry-pick',
|
||||||
|
' * reset',
|
||||||
|
' * revert',
|
||||||
|
' * rebase',
|
||||||
|
' * merge'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
type: 'ModalAlert',
|
||||||
|
options: {
|
||||||
|
markdowns: [
|
||||||
|
'## Teilen macht Spaß!',
|
||||||
|
'',
|
||||||
|
'Teile diese Git-Bäume mit deinen Freunden mittels `export tree` und `import tree`.',
|
||||||
|
'',
|
||||||
|
'Hast du Wissenswertes zu Git zu vermitteln? Versuch einen Level mit `build level` zu bauen oder probier den Level eines Freundes mit `import level` aus.',
|
||||||
|
'',
|
||||||
|
'Um alle Kommandos zu sehen, gib `show commands` ein. Darunter gibt\'s kleine Schätze wie `undo` und `reset`.',
|
||||||
|
'',
|
||||||
|
'Für\'s Erste lass uns mit `levels` anfangen ...'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}],
|
||||||
'ja': [{
|
'ja': [{
|
||||||
type: 'ModalAlert',
|
type: 'ModalAlert',
|
||||||
options: {
|
options: {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var intl = require('../intl');
|
var intl = require('../intl');
|
||||||
|
|
||||||
|
var Graph = require('../graph');
|
||||||
var Errors = require('../util/errors');
|
var Errors = require('../util/errors');
|
||||||
var CommandProcessError = Errors.CommandProcessError;
|
var CommandProcessError = Errors.CommandProcessError;
|
||||||
var GitError = Errors.GitError;
|
var GitError = Errors.GitError;
|
||||||
|
@ -47,8 +48,8 @@ var assertNotCheckedOut = function(engine, ref) {
|
||||||
|
|
||||||
var assertIsBranch = function(engine, ref) {
|
var assertIsBranch = function(engine, ref) {
|
||||||
assertIsRef(engine, ref);
|
assertIsRef(engine, ref);
|
||||||
var obj = engine.refs[ref];
|
var obj = engine.resolveID(ref);
|
||||||
if (obj.get('type') !== 'branch') {
|
if (!obj || obj.get('type') !== 'branch') {
|
||||||
throw new GitError({
|
throw new GitError({
|
||||||
msg: intl.todo(
|
msg: intl.todo(
|
||||||
ref + ' is not a branch'
|
ref + ' is not a branch'
|
||||||
|
@ -59,7 +60,7 @@ var assertIsBranch = function(engine, ref) {
|
||||||
|
|
||||||
var assertIsRemoteBranch = function(engine, ref) {
|
var assertIsRemoteBranch = function(engine, ref) {
|
||||||
assertIsRef(engine, ref);
|
assertIsRef(engine, ref);
|
||||||
var obj = engine.refs[ref];
|
var obj = engine.resolveID(ref);
|
||||||
|
|
||||||
if (obj.get('type') !== 'branch' ||
|
if (obj.get('type') !== 'branch' ||
|
||||||
!obj.getIsRemote()) {
|
!obj.getIsRemote()) {
|
||||||
|
@ -86,7 +87,7 @@ var assertOriginSpecified = function(generalArgs) {
|
||||||
|
|
||||||
var assertBranchIsRemoteTracking = function(engine, branchName) {
|
var assertBranchIsRemoteTracking = function(engine, branchName) {
|
||||||
branchName = crappyUnescape(branchName);
|
branchName = crappyUnescape(branchName);
|
||||||
if (!engine.refs[branchName]) {
|
if (!engine.resolveID(branchName)) {
|
||||||
throw new GitError({
|
throw new GitError({
|
||||||
msg: intl.todo(branchName + ' is not a branch!')
|
msg: intl.todo(branchName + ' is not a branch!')
|
||||||
});
|
});
|
||||||
|
@ -177,7 +178,7 @@ var commandConfig = {
|
||||||
|
|
||||||
command.validateArgBounds(generalArgs, 1, Number.MAX_VALUE);
|
command.validateArgBounds(generalArgs, 1, Number.MAX_VALUE);
|
||||||
|
|
||||||
var set = engine.getUpstreamSet('HEAD');
|
var set = Graph.getUpstreamSet(engine, 'HEAD');
|
||||||
// first resolve all the refs (as an error check)
|
// first resolve all the refs (as an error check)
|
||||||
var toCherrypick = _.map(generalArgs, function(arg) {
|
var toCherrypick = _.map(generalArgs, function(arg) {
|
||||||
var commit = engine.getCommitFromRef(arg);
|
var commit = engine.getCommitFromRef(arg);
|
||||||
|
@ -696,7 +697,7 @@ var commandConfig = {
|
||||||
// can be created on demand but we at least need this to be a source
|
// can be created on demand but we at least need this to be a source
|
||||||
// locally otherwise we will fail
|
// locally otherwise we will fail
|
||||||
assertIsRef(engine, firstArg);
|
assertIsRef(engine, firstArg);
|
||||||
sourceObj = engine.refs[firstArg];
|
sourceObj = engine.resolveID(firstArg);
|
||||||
} else {
|
} else {
|
||||||
// since they have not specified a source or destination, then
|
// since they have not specified a source or destination, then
|
||||||
// we source from the branch we are on (or HEAD)
|
// we source from the branch we are on (or HEAD)
|
||||||
|
|
|
@ -27,12 +27,6 @@ function catchShortCircuit(err) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invariant(truthy, reason) {
|
|
||||||
if (!truthy) {
|
|
||||||
throw new Error(reason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function GitEngine(options) {
|
function GitEngine(options) {
|
||||||
this.rootCommit = null;
|
this.rootCommit = null;
|
||||||
this.refs = {};
|
this.refs = {};
|
||||||
|
@ -174,7 +168,7 @@ GitEngine.prototype.exportTreeForBranch = function(branchName) {
|
||||||
// is not connected to branchname
|
// is not connected to branchname
|
||||||
var tree = this.exportTree();
|
var tree = this.exportTree();
|
||||||
// get the upstream set
|
// get the upstream set
|
||||||
var set = this.getUpstreamSet(branchName);
|
var set = Graph.getUpstreamSet(this, branchName);
|
||||||
// now loop through and delete commits
|
// now loop through and delete commits
|
||||||
var commitsToLoop = tree.commits;
|
var commitsToLoop = tree.commits;
|
||||||
tree.commits = {};
|
tree.commits = {};
|
||||||
|
@ -624,6 +618,14 @@ GitEngine.prototype.validateBranchName = function(name) {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (/^[cC]\d+$/.test(name)) {
|
||||||
|
throw new GitError({
|
||||||
|
msg: intl.str(
|
||||||
|
'bad-branch-name',
|
||||||
|
{ branch: name }
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
if (/[hH][eE][aA][dD]/.test(name)) {
|
if (/[hH][eE][aA][dD]/.test(name)) {
|
||||||
throw new GitError({
|
throw new GitError({
|
||||||
msg: intl.str(
|
msg: intl.str(
|
||||||
|
@ -650,7 +652,7 @@ GitEngine.prototype.validateAndMakeBranch = function(id, target) {
|
||||||
throw new GitError({
|
throw new GitError({
|
||||||
msg: intl.str(
|
msg: intl.str(
|
||||||
'bad-branch-name',
|
'bad-branch-name',
|
||||||
{ branch: name }
|
{ branch: id }
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -934,7 +936,7 @@ GitEngine.prototype.checkUpstreamOfSource = function(
|
||||||
// target. Hence target should be strictly upstream of source
|
// target. Hence target should be strictly upstream of source
|
||||||
|
|
||||||
// lets first get the upstream set from source's dest branch
|
// lets first get the upstream set from source's dest branch
|
||||||
var upstream = source.getUpstreamSet(sourceBranch);
|
var upstream = Graph.getUpstreamSet(source, sourceBranch);
|
||||||
|
|
||||||
var targetLocationID = target.getCommitFromRef(targetBranch).get('id');
|
var targetLocationID = target.getCommitFromRef(targetBranch).get('id');
|
||||||
if (!upstream[targetLocationID]) {
|
if (!upstream[targetLocationID]) {
|
||||||
|
@ -954,7 +956,7 @@ GitEngine.prototype.getTargetGraphDifference = function(
|
||||||
options = options || {};
|
options = options || {};
|
||||||
sourceBranch = source.resolveID(sourceBranch);
|
sourceBranch = source.resolveID(sourceBranch);
|
||||||
|
|
||||||
var targetSet = target.getUpstreamSet(targetBranch);
|
var targetSet = Graph.getUpstreamSet(target, targetBranch);
|
||||||
var sourceStartCommit = source.getCommitFromRef(sourceBranch);
|
var sourceStartCommit = source.getCommitFromRef(sourceBranch);
|
||||||
|
|
||||||
var sourceTree = source.exportTree();
|
var sourceTree = source.exportTree();
|
||||||
|
@ -1357,7 +1359,24 @@ GitEngine.prototype.pullFinishWithRebase = function(
|
||||||
|
|
||||||
chain = chain.then(_.bind(function() {
|
chain = chain.then(_.bind(function() {
|
||||||
pendingFetch.dontResolvePromise = true;
|
pendingFetch.dontResolvePromise = true;
|
||||||
|
|
||||||
|
try {
|
||||||
return this.rebase(remoteBranch, localBranch, pendingFetch);
|
return this.rebase(remoteBranch, localBranch, pendingFetch);
|
||||||
|
} catch (err) {
|
||||||
|
this.filterError(err);
|
||||||
|
// we make one exception here to match the behavior of
|
||||||
|
// git pull --rebase. If the rebase is empty we just
|
||||||
|
// simply checkout the new location
|
||||||
|
if (err.getMsg() !== intl.str('git-error-rebase-none')) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
this.setTargetLocation(
|
||||||
|
localBranch,
|
||||||
|
this.getCommitFromRef(remoteBranch)
|
||||||
|
);
|
||||||
|
this.checkout(localBranch);
|
||||||
|
return this.animationFactory.playRefreshAnimation(this.gitVisuals);
|
||||||
|
}
|
||||||
}, this));
|
}, this));
|
||||||
chain = chain.fail(catchShortCircuit);
|
chain = chain.fail(catchShortCircuit);
|
||||||
|
|
||||||
|
@ -1707,7 +1726,7 @@ GitEngine.prototype.pruneTreeAndPlay = function() {
|
||||||
GitEngine.prototype.pruneTree = function() {
|
GitEngine.prototype.pruneTree = function() {
|
||||||
var set = this.getUpstreamBranchSet();
|
var set = this.getUpstreamBranchSet();
|
||||||
// dont prune commits that HEAD depends on
|
// dont prune commits that HEAD depends on
|
||||||
var headSet = this.getUpstreamSet('HEAD');
|
var headSet = Graph.getUpstreamSet(this, 'HEAD');
|
||||||
_.each(headSet, function(val, commitID) {
|
_.each(headSet, function(val, commitID) {
|
||||||
set[commitID] = true;
|
set[commitID] = true;
|
||||||
});
|
});
|
||||||
|
@ -1802,7 +1821,7 @@ GitEngine.prototype.getUpstreamCollectionSet = function(collection) {
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.getUpstreamHeadSet = function() {
|
GitEngine.prototype.getUpstreamHeadSet = function() {
|
||||||
var set = this.getUpstreamSet('HEAD');
|
var set = Graph.getUpstreamSet(this, 'HEAD');
|
||||||
var including = this.getCommitFromRef('HEAD').get('id');
|
var including = this.getCommitFromRef('HEAD').get('id');
|
||||||
|
|
||||||
set[including] = true;
|
set[including] = true;
|
||||||
|
@ -1950,7 +1969,7 @@ GitEngine.prototype.hgRebase = function(destination, base) {
|
||||||
// we need everything BELOW ourselves...
|
// we need everything BELOW ourselves...
|
||||||
var downstream = this.getDownstreamSet(base);
|
var downstream = this.getDownstreamSet(base);
|
||||||
// and we need to go upwards to the stop set
|
// and we need to go upwards to the stop set
|
||||||
var stopSet = this.getUpstreamSet(destination);
|
var stopSet = Graph.getUpstreamSet(this, destination);
|
||||||
var upstream = this.getUpstreamDiffSetFromSet(stopSet, base);
|
var upstream = this.getUpstreamDiffSetFromSet(stopSet, base);
|
||||||
|
|
||||||
// and NOWWWwwww get all the descendants of this set
|
// and NOWWWwwww get all the descendants of this set
|
||||||
|
@ -2032,7 +2051,7 @@ GitEngine.prototype.rebase = function(targetSource, currentLocation, options) {
|
||||||
// then we BFS from currentLocation, using the downstream set as our stopping point.
|
// then we BFS from currentLocation, using the downstream set as our stopping point.
|
||||||
// we need to BFS because we need to include all commits below
|
// we need to BFS because we need to include all commits below
|
||||||
// pop these commits on top of targetSource and modify their ids with quotes
|
// pop these commits on top of targetSource and modify their ids with quotes
|
||||||
var stopSet = this.getUpstreamSet(targetSource);
|
var stopSet = Graph.getUpstreamSet(this, targetSource);
|
||||||
var toRebaseRough = this.getUpstreamDiffFromSet(stopSet, currentLocation);
|
var toRebaseRough = this.getUpstreamDiffFromSet(stopSet, currentLocation);
|
||||||
return this.rebaseFinish(toRebaseRough, stopSet, targetSource, currentLocation, options);
|
return this.rebaseFinish(toRebaseRough, stopSet, targetSource, currentLocation, options);
|
||||||
};
|
};
|
||||||
|
@ -2064,7 +2083,7 @@ GitEngine.prototype.rebaseInteractive = function(targetSource, currentLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
// now get the stop set
|
// now get the stop set
|
||||||
var stopSet = this.getUpstreamSet(targetSource);
|
var stopSet = Graph.getUpstreamSet(this, targetSource);
|
||||||
|
|
||||||
var toRebaseRough = [];
|
var toRebaseRough = [];
|
||||||
// standard BFS
|
// standard BFS
|
||||||
|
@ -2567,7 +2586,7 @@ GitEngine.prototype.status = function() {
|
||||||
GitEngine.prototype.logWithout = function(ref, omitBranch) {
|
GitEngine.prototype.logWithout = function(ref, omitBranch) {
|
||||||
// slice off the ^branch
|
// slice off the ^branch
|
||||||
omitBranch = omitBranch.slice(1);
|
omitBranch = omitBranch.slice(1);
|
||||||
this.log(ref, this.getUpstreamSet(omitBranch));
|
this.log(ref, Graph.getUpstreamSet(this, omitBranch));
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.log = function(ref, omitSet) {
|
GitEngine.prototype.log = function(ref, omitSet) {
|
||||||
|
@ -2612,7 +2631,7 @@ GitEngine.prototype.getCommonAncestor = function(ancestor, cousin) {
|
||||||
throw new Error('Dont use common ancestor if we are upstream!');
|
throw new Error('Dont use common ancestor if we are upstream!');
|
||||||
}
|
}
|
||||||
|
|
||||||
var upstreamSet = this.getUpstreamSet(ancestor);
|
var upstreamSet = Graph.getUpstreamSet(this, ancestor);
|
||||||
// now BFS off of cousin until you find something
|
// now BFS off of cousin until you find something
|
||||||
|
|
||||||
var queue = [this.getCommitFromRef(cousin)];
|
var queue = [this.getCommitFromRef(cousin)];
|
||||||
|
@ -2631,7 +2650,7 @@ GitEngine.prototype.isUpstreamOf = function(child, ancestor) {
|
||||||
|
|
||||||
// basically just do a completely BFS search on ancestor to the root, then
|
// basically just do a completely BFS search on ancestor to the root, then
|
||||||
// check for membership of child in that set of explored nodes
|
// check for membership of child in that set of explored nodes
|
||||||
var upstream = this.getUpstreamSet(ancestor);
|
var upstream = Graph.getUpstreamSet(this, ancestor);
|
||||||
return upstream[child.get('id')] !== undefined;
|
return upstream[child.get('id')] !== undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2658,29 +2677,6 @@ GitEngine.prototype.getDownstreamSet = function(ancestor) {
|
||||||
return exploredSet;
|
return exploredSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
GitEngine.prototype.getUpstreamSet = function(ancestor) {
|
|
||||||
var commit = this.getCommitFromRef(ancestor);
|
|
||||||
var ancestorID = commit.get('id');
|
|
||||||
var queue = [commit];
|
|
||||||
|
|
||||||
var exploredSet = {};
|
|
||||||
exploredSet[ancestorID] = true;
|
|
||||||
|
|
||||||
var addToExplored = function(rent) {
|
|
||||||
exploredSet[rent.get('id')] = true;
|
|
||||||
queue.push(rent);
|
|
||||||
};
|
|
||||||
|
|
||||||
while (queue.length) {
|
|
||||||
var here = queue.pop();
|
|
||||||
var rents = here.get('parents');
|
|
||||||
|
|
||||||
_.each(rents, addToExplored);
|
|
||||||
}
|
|
||||||
return exploredSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var Ref = Backbone.Model.extend({
|
var Ref = Backbone.Model.extend({
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
if (!this.get('target')) {
|
if (!this.get('target')) {
|
||||||
|
@ -2741,7 +2737,6 @@ var Branch = Ref.extend({
|
||||||
*
|
*
|
||||||
* With that in mind, we change our branch model to support the following
|
* With that in mind, we change our branch model to support the following
|
||||||
*/
|
*/
|
||||||
|
|
||||||
setRemoteTrackingBranchID: function(id) {
|
setRemoteTrackingBranchID: function(id) {
|
||||||
this.set('remoteTrackingBranchID', id);
|
this.set('remoteTrackingBranchID', id);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
|
|
||||||
var Git = require('../git');
|
function invariant(truthy, reason) {
|
||||||
var Commit = Git.Commit;
|
if (!truthy) {
|
||||||
var Branch = Git.Branch;
|
throw new Error(reason);
|
||||||
var Tag = Git.Tag;
|
}
|
||||||
var Ref = Git.Ref;
|
}
|
||||||
|
|
||||||
var Graph = {
|
var Graph = {
|
||||||
|
|
||||||
getOrMakeRecursive: function(
|
getOrMakeRecursive: function(
|
||||||
tree,
|
tree,
|
||||||
createdSoFar,
|
createdSoFar,
|
||||||
objID,
|
objID,
|
||||||
gitVisuals
|
gitVisuals
|
||||||
) {
|
) {
|
||||||
|
// circular dependency, should move these base models OUT of
|
||||||
|
// the git class to resolve this
|
||||||
|
var Git = require('../git');
|
||||||
|
var Commit = Git.Commit;
|
||||||
|
var Ref = Git.Ref;
|
||||||
|
var Branch = Git.Branch;
|
||||||
|
var Tag = Git.Tag;
|
||||||
if (createdSoFar[objID]) {
|
if (createdSoFar[objID]) {
|
||||||
// base case
|
// base case
|
||||||
return createdSoFar[objID];
|
return createdSoFar[objID];
|
||||||
|
@ -118,6 +126,28 @@ var Graph = {
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getUpstreamSet: function(engine, ancestor) {
|
||||||
|
var commit = engine.getCommitFromRef(ancestor);
|
||||||
|
var ancestorID = commit.get('id');
|
||||||
|
var queue = [commit];
|
||||||
|
|
||||||
|
var exploredSet = {};
|
||||||
|
exploredSet[ancestorID] = true;
|
||||||
|
|
||||||
|
var addToExplored = function(rent) {
|
||||||
|
exploredSet[rent.get('id')] = true;
|
||||||
|
queue.push(rent);
|
||||||
|
};
|
||||||
|
|
||||||
|
while (queue.length) {
|
||||||
|
var here = queue.pop();
|
||||||
|
var rents = here.get('parents');
|
||||||
|
|
||||||
|
_.each(rents, addToExplored);
|
||||||
|
}
|
||||||
|
return exploredSet;
|
||||||
|
},
|
||||||
|
|
||||||
getUniqueObjects: function(objects) {
|
getUniqueObjects: function(objects) {
|
||||||
var unique = {};
|
var unique = {};
|
||||||
var result = [];
|
var result = [];
|
||||||
|
|
|
@ -5,6 +5,9 @@ var TreeCompare = {};
|
||||||
|
|
||||||
TreeCompare.dispatchFromLevel = function(levelBlob, treeToCompare) {
|
TreeCompare.dispatchFromLevel = function(levelBlob, treeToCompare) {
|
||||||
var goalTreeString = levelBlob.goalTreeString;
|
var goalTreeString = levelBlob.goalTreeString;
|
||||||
|
if (typeof treeToCompare !== 'string') {
|
||||||
|
console.warn('NEED to pass in string!! gah');
|
||||||
|
}
|
||||||
return TreeCompare.dispatch(levelBlob, goalTreeString, treeToCompare);
|
return TreeCompare.dispatch(levelBlob, goalTreeString, treeToCompare);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,7 +83,7 @@ TreeCompare.compareAllBranchesWithinTreesAndHEAD = function(treeA, treeB) {
|
||||||
treeB = this.convertTreeSafe(treeB);
|
treeB = this.convertTreeSafe(treeB);
|
||||||
|
|
||||||
// also compare tags!! for just one level
|
// also compare tags!! for just one level
|
||||||
return treeA.HEAD.target == treeB.HEAD.target &&
|
return treeA.HEAD.target === treeB.HEAD.target &&
|
||||||
this.compareAllBranchesWithinTrees(treeA, treeB) &&
|
this.compareAllBranchesWithinTrees(treeA, treeB) &&
|
||||||
this.compareAllTagsWithinTrees(treeA, treeB);
|
this.compareAllTagsWithinTrees(treeA, treeB);
|
||||||
};
|
};
|
||||||
|
@ -319,9 +322,31 @@ TreeCompare.getRecurseCompare = function(treeA, treeB, options) {
|
||||||
return recurseCompare;
|
return recurseCompare;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TreeCompare.lowercaseTree = function(tree) {
|
||||||
|
if (tree.HEAD) {
|
||||||
|
tree.HEAD.target = tree.HEAD.target.toLocaleLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
var branches = tree.branches;
|
||||||
|
tree.branches = {};
|
||||||
|
_.each(branches, function(obj, name) {
|
||||||
|
obj.id = obj.id.toLocaleLowerCase();
|
||||||
|
tree.branches[name.toLocaleLowerCase()] = obj;
|
||||||
|
});
|
||||||
|
return tree;
|
||||||
|
};
|
||||||
|
|
||||||
TreeCompare.convertTreeSafe = function(tree) {
|
TreeCompare.convertTreeSafe = function(tree) {
|
||||||
if (typeof tree == 'string') {
|
if (typeof tree !== 'string') {
|
||||||
return JSON.parse(unescape(tree));
|
return tree;
|
||||||
|
}
|
||||||
|
tree = JSON.parse(unescape(tree));
|
||||||
|
// ok we are almost done -- but we need to case insensitive
|
||||||
|
// certain fields. so go ahead and do that.
|
||||||
|
// handle HEAD target first
|
||||||
|
this.lowercaseTree(tree);
|
||||||
|
if (tree.originTree) {
|
||||||
|
tree.originTree = this.lowercaseTree(tree.originTree);
|
||||||
}
|
}
|
||||||
return tree;
|
return tree;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
var sys = require('sys');
|
var sys = require('sys');
|
||||||
|
var util = require('../util');
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var child_process = require('child_process');
|
var child_process = require('child_process');
|
||||||
var strings = require('../intl/strings').strings;
|
var strings = require('../intl/strings').strings;
|
||||||
|
@ -39,9 +40,11 @@ var processLines = function(lines) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!util.isBrowser()) {
|
||||||
child_process.exec(
|
child_process.exec(
|
||||||
searchCommand,
|
searchCommand,
|
||||||
function(err, output) {
|
function(err, output) {
|
||||||
processLines(output.split('\n'));
|
processLines(output.split('\n'));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var constants = require('../util/constants');
|
var constants = require('../util/constants');
|
||||||
var util = require('../util');
|
var util = require('../util');
|
||||||
|
var GlobalState = require('../util/globalState');
|
||||||
|
|
||||||
var strings = require('../intl/strings').strings;
|
var strings = require('../intl/strings').strings;
|
||||||
|
|
||||||
|
@ -9,8 +10,8 @@ var getDefaultLocale = exports.getDefaultLocale = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
var getLocale = exports.getLocale = function() {
|
var getLocale = exports.getLocale = function() {
|
||||||
if (constants.GLOBAL.locale) {
|
if (GlobalState.locale) {
|
||||||
return constants.GLOBAL.locale;
|
return GlobalState.locale;
|
||||||
}
|
}
|
||||||
return getDefaultLocale();
|
return getDefaultLocale();
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ exports.strings = {
|
||||||
'__desc__': 'One of the lines in the next level dialog',
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
'ja': '最後のレベルをクリアしました!すごい!!',
|
'ja': '最後のレベルをクリアしました!すごい!!',
|
||||||
'en_US': 'Wow! You finished the last level, great!',
|
'en_US': 'Wow! You finished the last level, great!',
|
||||||
|
'de_DE': 'Wow! Du hast den letzten Level gelöst, super!',
|
||||||
'zh_CN': '我的个天!你完成了最后一关,碉堡了!',
|
'zh_CN': '我的个天!你完成了最后一关,碉堡了!',
|
||||||
'zh_TW': '我的天啊!您解開了最後一關,太強了!',
|
'zh_TW': '我的天啊!您解開了最後一關,太強了!',
|
||||||
'fr_FR': 'Félicitations, vous avez réussi le dernier niveau !'
|
'fr_FR': 'Félicitations, vous avez réussi le dernier niveau !'
|
||||||
|
@ -12,6 +13,7 @@ exports.strings = {
|
||||||
'finish-dialog-next': {
|
'finish-dialog-next': {
|
||||||
'__desc__': 'One of the lines in the next level dialog',
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
'en_US': 'Would you like to move on to *"{nextLevel}"*, the next level?',
|
'en_US': 'Would you like to move on to *"{nextLevel}"*, the next level?',
|
||||||
|
'de_DE': 'Möchtest du mit *"{nextLevel}"* weitermachen, dem nächsten Level?',
|
||||||
'ja': '次の章 *"{nextLevel}"* へ進みますか?',
|
'ja': '次の章 *"{nextLevel}"* へ進みますか?',
|
||||||
'zh_CN': '要不前进到下一关 *“{nextLevel}”*?',
|
'zh_CN': '要不前进到下一关 *“{nextLevel}”*?',
|
||||||
'zh_TW': '下一關是*「{nextLevel}」*,您要繼續闖關嗎?',
|
'zh_TW': '下一關是*「{nextLevel}」*,您要繼續闖關嗎?',
|
||||||
|
@ -21,6 +23,7 @@ exports.strings = {
|
||||||
'finish-dialog-win': {
|
'finish-dialog-win': {
|
||||||
'__desc__': 'One of the lines in the next level dialog',
|
'__desc__': 'One of the lines in the next level dialog',
|
||||||
'en_US': 'Awesome! You matched or exceeded our solution.',
|
'en_US': 'Awesome! You matched or exceeded our solution.',
|
||||||
|
'de_DE': 'Wahnsinn! Du warst so gut wie unsere Lösung, oder sogar besser.',
|
||||||
'ja': '素晴らしい!このレベルをクリアしましたね。',
|
'ja': '素晴らしい!このレベルをクリアしましたね。',
|
||||||
'zh_CN': '牛鼻啊!你达到或者完爆了我们的答案。',
|
'zh_CN': '牛鼻啊!你达到或者完爆了我们的答案。',
|
||||||
'zh_TW': '太強了,您的答案符合我們的預期甚至更好!',
|
'zh_TW': '太強了,您的答案符合我們的預期甚至更好!',
|
||||||
|
@ -30,6 +33,7 @@ exports.strings = {
|
||||||
'finish-dialog-lose': {
|
'finish-dialog-lose': {
|
||||||
'__desc__': 'When the user entered more commands than our best, encourage them to do better',
|
'__desc__': 'When the user entered more commands than our best, encourage them to do better',
|
||||||
'en_US': 'See if you can whittle it down to {best} :D',
|
'en_US': 'See if you can whittle it down to {best} :D',
|
||||||
|
'de_DE': 'Schau mal ob du es in {best} Schritten hinbekommst :D',
|
||||||
'ja': '模範解答の回数={best}回でクリアする方法も考えてみましょう :D',
|
'ja': '模範解答の回数={best}回でクリアする方法も考えてみましょう :D',
|
||||||
'zh_CN': '试试看你能否在 {best} 之内搞定 :D',
|
'zh_CN': '试试看你能否在 {best} 之内搞定 :D',
|
||||||
'zh_TW': '試試看您是否能在 {best} 步内搞定 :D',
|
'zh_TW': '試試看您是否能在 {best} 步内搞定 :D',
|
||||||
|
@ -38,32 +42,38 @@ exports.strings = {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'hg-prune-tree': {
|
'hg-prune-tree': {
|
||||||
'__desc__': 'warning when pruning tree',
|
'__desc__': 'warning when pruning tree',
|
||||||
'en_US': 'Warning! Mercurial does aggressive garbage collection and thus needs to prune your tree'
|
'en_US': 'Warning! Mercurial does aggressive garbage collection and thus needs to prune your tree',
|
||||||
|
'de_DE': 'Achtung! Mercurial macht aggressive Garbage Collection und muss daher deinen Baum reduzieren'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'hg-a-option': {
|
'hg-a-option': {
|
||||||
'__desc__': 'warning for when using -A option',
|
'__desc__': 'warning for when using -A option',
|
||||||
'en_US': 'The -A option is not needed for this app, just commit away!'
|
'en_US': 'The -A option is not needed for this app, just commit away!',
|
||||||
|
'de_DE': 'Die Option -A wird in dieser Anwendung nicht benötigt, committe einfach!'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'hg-error-no-status': {
|
'hg-error-no-status': {
|
||||||
'__desc__': 'One of the errors for hg',
|
'__desc__': 'One of the errors for hg',
|
||||||
'en_US': 'There is no status command for this app, since there is no staging of files. Try hg summary instead'
|
'en_US': 'There is no status command for this app, since there is no staging of files. Try hg summary instead',
|
||||||
|
'de_DE': 'Es gibt keinen Befehl status in dieser Anwendung, da es kein Staging von Dateien gibt. Probier stattdessen hg summary'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'hg-error-need-option': {
|
'hg-error-need-option': {
|
||||||
'__desc__': 'One of the errors for hg',
|
'__desc__': 'One of the errors for hg',
|
||||||
'en_US': 'I need the option {option} for that command!'
|
'en_US': 'I need the option {option} for that command!',
|
||||||
|
'de_DE': 'Ich benötige die Option {option} für diesen Befehl!'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'hg-error-log-no-follow': {
|
'hg-error-log-no-follow': {
|
||||||
'__desc__': 'hg log without -f (--follow)',
|
'__desc__': 'hg log without -f (--follow)',
|
||||||
'en_US': 'hg log without -f is currently not supported, use -f'
|
'en_US': 'hg log without -f is currently not supported, use -f',
|
||||||
|
'de_DE': 'hg log ohne -f wird aktuell nicht unterstützt, benutze bitte -f'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'git-status-detached': {
|
'git-status-detached': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Detached head!',
|
'en_US': 'Detached head!',
|
||||||
|
'de_DE': 'Detached head!',
|
||||||
'zh_CN': '脑袋搬家(Detached head)了!',
|
'zh_CN': '脑袋搬家(Detached head)了!',
|
||||||
'zh_TW': '腦袋搬家(Detached head)了!',
|
'zh_TW': '腦袋搬家(Detached head)了!',
|
||||||
'fr_FR': 'head détaché !'
|
'fr_FR': 'head détaché !'
|
||||||
|
@ -72,6 +82,7 @@ exports.strings = {
|
||||||
'git-status-onbranch': {
|
'git-status-onbranch': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'On branch {branch}',
|
'en_US': 'On branch {branch}',
|
||||||
|
'de_DE': 'Auf Branch {branch}',
|
||||||
'zh_CN': '切换到分支 {branch}',
|
'zh_CN': '切换到分支 {branch}',
|
||||||
'zh_TW': '切換到分支 {branch}',
|
'zh_TW': '切換到分支 {branch}',
|
||||||
'fr_FR': 'Sur la branche {branch}'
|
'fr_FR': 'Sur la branche {branch}'
|
||||||
|
@ -80,6 +91,7 @@ exports.strings = {
|
||||||
'git-status-readytocommit': {
|
'git-status-readytocommit': {
|
||||||
'__desc__': 'One of the lines for git status output',
|
'__desc__': 'One of the lines for git status output',
|
||||||
'en_US': 'Ready to commit! (as always in this demo)',
|
'en_US': 'Ready to commit! (as always in this demo)',
|
||||||
|
'de_DE': 'Fertig zum committen! (Wie immer in dieser Demo)',
|
||||||
'zh_CN': '可以提交啦!(这演示里一直可以提交)',
|
'zh_CN': '可以提交啦!(这演示里一直可以提交)',
|
||||||
'zh_TW': '可以提交啦!(這演示裡一直可以提交)',
|
'zh_TW': '可以提交啦!(這演示裡一直可以提交)',
|
||||||
'fr_FR': 'Prêt à commit ! (comme toujours dans cette démo)'
|
'fr_FR': 'Prêt à commit ! (comme toujours dans cette démo)'
|
||||||
|
@ -89,6 +101,7 @@ exports.strings = {
|
||||||
'__desc__': 'The dummy commit message for all commits. Feel free to put in a ' +
|
'__desc__': 'The dummy commit message for all commits. Feel free to put in a ' +
|
||||||
'shoutout to your school / city / whatever!',
|
'shoutout to your school / city / whatever!',
|
||||||
'en_US': 'Quick commit. Go Bears!',
|
'en_US': 'Quick commit. Go Bears!',
|
||||||
|
'de_DE': 'Schneller Commit. Eff-Zeh!',
|
||||||
'zh_CN': '快速提交。上啊月熊!',
|
'zh_CN': '快速提交。上啊月熊!',
|
||||||
'zh_TW': '快速提交。上啊月熊!',
|
'zh_TW': '快速提交。上啊月熊!',
|
||||||
'fr_FR': 'Commit rapide. NoMaN Sux!'
|
'fr_FR': 'Commit rapide. NoMaN Sux!'
|
||||||
|
@ -96,31 +109,37 @@ exports.strings = {
|
||||||
'git-error-origin-fetch-uptodate': {
|
'git-error-origin-fetch-uptodate': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'Already up to date!',
|
'en_US': 'Already up to date!',
|
||||||
|
'de_DE': 'Bereits aktuell!',
|
||||||
'fr_FR': 'Déjà à jour'
|
'fr_FR': 'Déjà à jour'
|
||||||
},
|
},
|
||||||
'git-error-origin-fetch-no-ff': {
|
'git-error-origin-fetch-no-ff': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'Your origin branch is out of sync with the remote branch and fetch cannot be performed',
|
'en_US': 'Your origin branch is out of sync with the remote branch and fetch cannot be performed',
|
||||||
|
'de_DE': 'Dein origin Branch ist nicht auf dem Stand des Remote Branch und fetch kann nicht ausgeführt werden',
|
||||||
'fr_FR': 'Votre branche origin n\'est plus synchronisée avec la branche distante et fetch ne peut pas être appliqué. Essayez avec l\'option --force'
|
'fr_FR': 'Votre branche origin n\'est plus synchronisée avec la branche distante et fetch ne peut pas être appliqué. Essayez avec l\'option --force'
|
||||||
},
|
},
|
||||||
'git-error-origin-push-no-ff': {
|
'git-error-origin-push-no-ff': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'The remote repository has diverged from your local repository, so uploading your changes is not a simple fast forward (and thus your push was rejected). Please pull down the new changes in the remote repository, incorporate them into this branch, and try again. You can do so with git pull or git pull --rebase',
|
'en_US': 'The remote repository has diverged from your local repository, so uploading your changes is not a simple fast forward (and thus your push was rejected). Please pull down the new changes in the remote repository, incorporate them into this branch, and try again. You can do so with git pull or git pull --rebase',
|
||||||
|
'de_DE': 'Das entfernte Repository weicht von deinem lokalen Repository ab, daher können deine Änderungen nicht mit einem einfachen fast forward hochgeladen werden (und daher ist dein push abgelehnt worden). Bitte pull erst die neuen Änderungen in das lokale Repository, integriere sie in den Branch und versuch es nochmal. Das kannst du mit git pull oder git pull --rebase machen',
|
||||||
'fr_FR': 'Le dépôt distant a divergé de votre référentiel local, donc l\'envoi de vos modifications n\'est pas en simple avance rapide (et donc votre envoi a été rejeté). Veuillez récupérer les nouveaux changements depuis le dépôt distant, les intégrer dans cette branche, et essayez à nouveau. Vous pouvez le faire avec git pull ou git pull --rebase'
|
'fr_FR': 'Le dépôt distant a divergé de votre référentiel local, donc l\'envoi de vos modifications n\'est pas en simple avance rapide (et donc votre envoi a été rejeté). Veuillez récupérer les nouveaux changements depuis le dépôt distant, les intégrer dans cette branche, et essayez à nouveau. Vous pouvez le faire avec git pull ou git pull --rebase'
|
||||||
},
|
},
|
||||||
'git-error-remote-branch': {
|
'git-error-remote-branch': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'You cannot execute that command on a remote branch',
|
'en_US': 'You cannot execute that command on a remote branch',
|
||||||
|
'de_DE': 'Du kannst diesen Befehl nicht auf einem Remote Branch ausführen',
|
||||||
'fr_FR': 'Vous ne pouvez exécuter cette commande sur une branche distante'
|
'fr_FR': 'Vous ne pouvez exécuter cette commande sur une branche distante'
|
||||||
},
|
},
|
||||||
'git-error-origin-required': {
|
'git-error-origin-required': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'An origin is required for that command',
|
'en_US': 'An origin is required for that command',
|
||||||
|
'de_DE': 'Für diesen Befehl wird origin benötigt',
|
||||||
'fr_FR': 'Une origine est requise pour cette commande'
|
'fr_FR': 'Une origine est requise pour cette commande'
|
||||||
},
|
},
|
||||||
'git-error-origin-exists': {
|
'git-error-origin-exists': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'An origin already exists! You cannot make a new one',
|
'en_US': 'An origin already exists! You cannot make a new one',
|
||||||
|
'de_DE': 'origin existiert bereits! Du kannst es nicht nochmal anlegen',
|
||||||
'fr_FR': 'Une origine existe déjà ! Vous ne pouvez pas en créer une nouvelle'
|
'fr_FR': 'Une origine existe déjà ! Vous ne pouvez pas en créer une nouvelle'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -128,6 +147,7 @@ exports.strings = {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'You can\'t delete the master branch, the branch you are on, or things that ' +
|
'en_US': 'You can\'t delete the master branch, the branch you are on, or things that ' +
|
||||||
'aren\'t branches',
|
'aren\'t branches',
|
||||||
|
'de_DE': 'Du kannst nicht den Branch master, den Branch auf dem du gerade arbeitest oder Refs, die keine Branches sind, löschen',
|
||||||
'zh_CN': '你不能删除主分支(master),或者你当前所在的分支,或者其他不是分支也不知道能不能吃的东西。',
|
'zh_CN': '你不能删除主分支(master),或者你当前所在的分支,或者其他不是分支也不知道能不能吃的东西。',
|
||||||
'zh_TW': '你不能刪除主分支(master),或者你當前所在的分支,或者其他不是分支也不知道能不能吃的東西。',
|
'zh_TW': '你不能刪除主分支(master),或者你當前所在的分支,或者其他不是分支也不知道能不能吃的東西。',
|
||||||
'fr_FR': 'Vous ne pouvez supprimer la branche master, la branche sur laquelle vous êtes, ou ce qui n\'est pas une branche'
|
'fr_FR': 'Vous ne pouvez supprimer la branche master, la branche sur laquelle vous êtes, ou ce qui n\'est pas une branche'
|
||||||
|
@ -136,6 +156,7 @@ exports.strings = {
|
||||||
'git-merge-msg': {
|
'git-merge-msg': {
|
||||||
'__desc__': 'The commit message for a merge commit',
|
'__desc__': 'The commit message for a merge commit',
|
||||||
'en_US': 'Merge {target} into {current}',
|
'en_US': 'Merge {target} into {current}',
|
||||||
|
'de_DE': 'Mergen von {target} in {current}',
|
||||||
'zh_CN': '合并 {target} 到 {current}',
|
'zh_CN': '合并 {target} 到 {current}',
|
||||||
'zh_TW': '將 {target} 併入 {current}',
|
'zh_TW': '將 {target} 併入 {current}',
|
||||||
'fr_FR': 'Merge de {target} dans {current}'
|
'fr_FR': 'Merge de {target} dans {current}'
|
||||||
|
@ -144,6 +165,7 @@ exports.strings = {
|
||||||
'git-error-rebase-none': {
|
'git-error-rebase-none': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'No commits to rebase! Everything is a merge commit or changes already applied',
|
'en_US': 'No commits to rebase! Everything is a merge commit or changes already applied',
|
||||||
|
'de_DE': 'Keine Commits für Rebase gefunden! Alle Commits sind Merge Commits oder beinhalten nur schon vorhandene Änderungen',
|
||||||
'zh_CN': '没有需要 rebase 的提交!都是个合并提交,或者已经 rebase 过了。',
|
'zh_CN': '没有需要 rebase 的提交!都是个合并提交,或者已经 rebase 过了。',
|
||||||
'zh_TW': '沒有需要 rebase 的提交!每份提交皆已合併或套用變更了',
|
'zh_TW': '沒有需要 rebase 的提交!每份提交皆已合併或套用變更了',
|
||||||
'fr_FR': 'Aucune commit à rebaser ! Tout est soit un commit de merge, soit des modifications déjà appliquées'
|
'fr_FR': 'Aucune commit à rebaser ! Tout est soit un commit de merge, soit des modifications déjà appliquées'
|
||||||
|
@ -152,6 +174,7 @@ exports.strings = {
|
||||||
'git-result-nothing': {
|
'git-result-nothing': {
|
||||||
'__desc__': 'The message that explains the result of a git command',
|
'__desc__': 'The message that explains the result of a git command',
|
||||||
'en_US': 'Nothing to do...',
|
'en_US': 'Nothing to do...',
|
||||||
|
'de_DE': 'Nichts zu tun ...',
|
||||||
'zh_CN': '没啥鸟事……',
|
'zh_CN': '没啥鸟事……',
|
||||||
'zh_TW': '沒啥鳥事……',
|
'zh_TW': '沒啥鳥事……',
|
||||||
'fr_FR': 'Rien à effectuer…'
|
'fr_FR': 'Rien à effectuer…'
|
||||||
|
@ -160,6 +183,7 @@ exports.strings = {
|
||||||
'git-result-fastforward': {
|
'git-result-fastforward': {
|
||||||
'__desc__': 'The message that explains the result of a git command',
|
'__desc__': 'The message that explains the result of a git command',
|
||||||
'en_US': 'Fast forwarding...',
|
'en_US': 'Fast forwarding...',
|
||||||
|
'de_DE': 'Fast forward...',
|
||||||
'zh_CN': '快速前进……',
|
'zh_CN': '快速前进……',
|
||||||
'zh_TW': '快速前進……',
|
'zh_TW': '快速前進……',
|
||||||
'fr_FR': 'En avance rapide…'
|
'fr_FR': 'En avance rapide…'
|
||||||
|
@ -168,6 +192,7 @@ exports.strings = {
|
||||||
'git-result-uptodate': {
|
'git-result-uptodate': {
|
||||||
'__desc__': 'The message that explains the result of a git command',
|
'__desc__': 'The message that explains the result of a git command',
|
||||||
'en_US': 'Branch already up-to-date',
|
'en_US': 'Branch already up-to-date',
|
||||||
|
'de_DE': 'Branch ist bereits aktuell',
|
||||||
'zh_CN': '分支已经是最新啦',
|
'zh_CN': '分支已经是最新啦',
|
||||||
'zh_TW': '分支已經是最新啦',
|
'zh_TW': '分支已經是最新啦',
|
||||||
'fr_FR': 'Branche déjà à jour'
|
'fr_FR': 'Branche déjà à jour'
|
||||||
|
@ -176,6 +201,7 @@ exports.strings = {
|
||||||
'git-error-exist': {
|
'git-error-exist': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'The ref {ref} does not exist or is unknown',
|
'en_US': 'The ref {ref} does not exist or is unknown',
|
||||||
|
'de_DE': 'Die Ref {ref} existiert nicht oder ist unbekannt',
|
||||||
'zh_CN': '索引 {ref} 不存在,或者找不到。',
|
'zh_CN': '索引 {ref} 不存在,或者找不到。',
|
||||||
'zh_TW': '索引 {ref} 不存在,或者找不到。',
|
'zh_TW': '索引 {ref} 不存在,或者找不到。',
|
||||||
'fr_FR': 'La référence {ref} n\'existe pas ou est inconnue'
|
'fr_FR': 'La référence {ref} n\'existe pas ou est inconnue'
|
||||||
|
@ -184,6 +210,7 @@ exports.strings = {
|
||||||
'git-error-relative-ref': {
|
'git-error-relative-ref': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'Commit {commit} doesnot have a {match}',
|
'en_US': 'Commit {commit} doesnot have a {match}',
|
||||||
|
'de_DE': 'Commit {commit} hat kein {match}',
|
||||||
'zh_CN': '提交 {commit} 并没有 {match}',
|
'zh_CN': '提交 {commit} 并没有 {match}',
|
||||||
'zh_TW': '提交 {commit} 並没有 {match}',
|
'zh_TW': '提交 {commit} 並没有 {match}',
|
||||||
'fr_FR': 'Le commit {commit} n\'a pas de correspondance {match}'
|
'fr_FR': 'Le commit {commit} n\'a pas de correspondance {match}'
|
||||||
|
@ -192,6 +219,7 @@ exports.strings = {
|
||||||
'git-warning-detached': {
|
'git-warning-detached': {
|
||||||
'__desc__': 'One of the warning messages for git',
|
'__desc__': 'One of the warning messages for git',
|
||||||
'en_US': 'Warning!! Detached HEAD state',
|
'en_US': 'Warning!! Detached HEAD state',
|
||||||
|
'de_DE': 'Achtung! Detached HEAD Zustand',
|
||||||
'zh_CN': '警告!脑袋搬家(Detached HEAD)状态',
|
'zh_CN': '警告!脑袋搬家(Detached HEAD)状态',
|
||||||
'zh_TW': '警告!腦袋搬家(Detached HEAD)狀態',
|
'zh_TW': '警告!腦袋搬家(Detached HEAD)狀態',
|
||||||
'fr_FR': 'Attention ! HEAD est détaché'
|
'fr_FR': 'Attention ! HEAD est détaché'
|
||||||
|
@ -200,6 +228,7 @@ exports.strings = {
|
||||||
'git-warning-add': {
|
'git-warning-add': {
|
||||||
'__desc__': 'One of the warning messages for git',
|
'__desc__': 'One of the warning messages for git',
|
||||||
'en_US': 'No need to add files in this demo',
|
'en_US': 'No need to add files in this demo',
|
||||||
|
'de_DE': 'In dieser Demo müssen keine Dateien hinzugefügt werden',
|
||||||
'zh_CN': '此演示中不需要添加文件',
|
'zh_CN': '此演示中不需要添加文件',
|
||||||
'zh_TW': '此演示中不需要添加文件',
|
'zh_TW': '此演示中不需要添加文件',
|
||||||
'fr_FR': 'Aucun besoin d\'ajouter des fichiers dans cette démo'
|
'fr_FR': 'Aucun besoin d\'ajouter des fichiers dans cette démo'
|
||||||
|
@ -208,6 +237,7 @@ exports.strings = {
|
||||||
'git-error-options': {
|
'git-error-options': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'Those options you specified are incompatible or incorrect',
|
'en_US': 'Those options you specified are incompatible or incorrect',
|
||||||
|
'de_DE': 'Die angegebenen Optionen sind inkompatibel oder falsch',
|
||||||
'zh_CN': '你所指定的参数不兼容或者不准确',
|
'zh_CN': '你所指定的参数不兼容或者不准确',
|
||||||
'zh_TW': '您指定了不相容或錯誤的選項',
|
'zh_TW': '您指定了不相容或錯誤的選項',
|
||||||
'fr_FR': 'Les options que vous avez spécifiées sont incompatibles ou incorrectes'
|
'fr_FR': 'Les options que vous avez spécifiées sont incompatibles ou incorrectes'
|
||||||
|
@ -216,6 +246,7 @@ exports.strings = {
|
||||||
'git-error-already-exists': {
|
'git-error-already-exists': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'The commit {commit} already exists in your changes set, aborting!',
|
'en_US': 'The commit {commit} already exists in your changes set, aborting!',
|
||||||
|
'de_DE': 'Der Commit {commit} existiert bereit, Abbruch!',
|
||||||
'zh_CN': '提交 {commit} 已经存在于你的改动集里,正在中止!',
|
'zh_CN': '提交 {commit} 已经存在于你的改动集里,正在中止!',
|
||||||
'zh_TW': '提交 {commit} 已經存在於你的改動集裡,正在中止!',
|
'zh_TW': '提交 {commit} 已經存在於你的改動集裡,正在中止!',
|
||||||
'fr_FR': 'Le commit {commit} existe déjà dans votre ensemble de modifications, opération avortée !'
|
'fr_FR': 'Le commit {commit} existe déjà dans votre ensemble de modifications, opération avortée !'
|
||||||
|
@ -224,6 +255,7 @@ exports.strings = {
|
||||||
'git-error-reset-detached': {
|
'git-error-reset-detached': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'Can\'t reset in detached head! Use checkout if you want to move',
|
'en_US': 'Can\'t reset in detached head! Use checkout if you want to move',
|
||||||
|
'de_DE': 'Kann im Detached Head Zustand kein reset ausführen! Bitte checkout zum Bewegen benutzen',
|
||||||
'zh_CN': '不能在分离的 HEAD 里重置!用 checkout 吧',
|
'zh_CN': '不能在分离的 HEAD 里重置!用 checkout 吧',
|
||||||
'zh_TW': '不能在分離的 HEAD 裡重置!用 checkout 吧',
|
'zh_TW': '不能在分離的 HEAD 裡重置!用 checkout 吧',
|
||||||
'fr_FR': 'On ne peut pas effectuer un reset quand head est détaché. Utilisez checkout pour déplacer'
|
'fr_FR': 'On ne peut pas effectuer un reset quand head est détaché. Utilisez checkout pour déplacer'
|
||||||
|
@ -232,6 +264,7 @@ exports.strings = {
|
||||||
'git-warning-hard': {
|
'git-warning-hard': {
|
||||||
'__desc__': 'One of the warning messages for git',
|
'__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 is a --hard reset, feel free to omit that option!',
|
||||||
|
'de_DE': 'Das Standardverhalten in dieser Demo ist --hard, du kannst die Option auch weglassen!',
|
||||||
'zh_CN': '默认的行为是 --hard 硬重置,尽管省略掉那个选项吧!',
|
'zh_CN': '默认的行为是 --hard 硬重置,尽管省略掉那个选项吧!',
|
||||||
'zh_TW': '默認的行為是 --hard 硬重置,盡管省略掉那個選項吧!',
|
'zh_TW': '默認的行為是 --hard 硬重置,盡管省略掉那個選項吧!',
|
||||||
'fr_FR': 'Le comportement par défaut est un --hard reset, soyez libre d\'omettre cette option !'
|
'fr_FR': 'Le comportement par défaut est un --hard reset, soyez libre d\'omettre cette option !'
|
||||||
|
@ -241,6 +274,7 @@ exports.strings = {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'There is no concept of adding / staging files, so that option or ' +
|
'en_US': 'There is no concept of adding / staging files, so that option or ' +
|
||||||
'command is invalid!',
|
'command is invalid!',
|
||||||
|
'de_DE': 'In dieser Demo gibt es kein Hinzufügen / Vormerken von Dateien, dieser Befehl ist daher ungültig!',
|
||||||
'zh_CN': '没有添加、缓存文件的必要,所以改选项或者命令是不合法的。',
|
'zh_CN': '没有添加、缓存文件的必要,所以改选项或者命令是不合法的。',
|
||||||
'zh_TW': '沒有添加、緩存文件的必要,所以改選項或者命令是不合法的。',
|
'zh_TW': '沒有添加、緩存文件的必要,所以改選項或者命令是不合法的。',
|
||||||
'fr_FR': 'Il n\'y a pas le concept d\'ajouter / mettre en staging, donc cette option ou commande est invalide'
|
'fr_FR': 'Il n\'y a pas le concept d\'ajouter / mettre en staging, donc cette option ou commande est invalide'
|
||||||
|
@ -249,6 +283,7 @@ exports.strings = {
|
||||||
'git-revert-msg': {
|
'git-revert-msg': {
|
||||||
'__desc__': 'Message for reverting git command',
|
'__desc__': 'Message for reverting git command',
|
||||||
'en_US': 'Reverting {oldCommit}: {oldMsg}',
|
'en_US': 'Reverting {oldCommit}: {oldMsg}',
|
||||||
|
'de_DE': 'Reverte {oldCommit}: {oldMsg}',
|
||||||
'zh_CN': '撤销 {oldCommit}:{oldMsg}',
|
'zh_CN': '撤销 {oldCommit}:{oldMsg}',
|
||||||
'zh_TW': '還原 {oldCommit}:{oldMsg}',
|
'zh_TW': '還原 {oldCommit}:{oldMsg}',
|
||||||
'fr_FR': 'Revert {oldCommit}: {oldMsg}'
|
'fr_FR': 'Revert {oldCommit}: {oldMsg}'
|
||||||
|
@ -257,6 +292,7 @@ exports.strings = {
|
||||||
'git-error-args-many': {
|
'git-error-args-many': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'I expect at most {upper} argument(s) for {what}',
|
'en_US': 'I expect at most {upper} argument(s) for {what}',
|
||||||
|
'de_DE': 'Ich benötige maximal {upper} Argument(e) für {what}',
|
||||||
'zh_CN': '{what} 期望最多 {upper} 个参数',
|
'zh_CN': '{what} 期望最多 {upper} 个参数',
|
||||||
'zh_TW': '{what} 期望最多 {upper} 個參數',
|
'zh_TW': '{what} 期望最多 {upper} 個參數',
|
||||||
'fr_FR': 'J\'attends au plus {upper} argument(s) pour {what}'
|
'fr_FR': 'J\'attends au plus {upper} argument(s) pour {what}'
|
||||||
|
@ -265,6 +301,7 @@ exports.strings = {
|
||||||
'git-error-args-few': {
|
'git-error-args-few': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'I expect at least {lower} argument(s) for {what}',
|
'en_US': 'I expect at least {lower} argument(s) for {what}',
|
||||||
|
'de_DE': 'Ich benötige mindestens {lower} Argument(e) für {what}',
|
||||||
'zh_CN': '{what} 期望最少 {lower} 个参数',
|
'zh_CN': '{what} 期望最少 {lower} 个参数',
|
||||||
'zh_TW': '{what} 期望最少 {lower} 個參數',
|
'zh_TW': '{what} 期望最少 {lower} 個參數',
|
||||||
'fr_FR': 'J\'attends au moins {upper} argument(s) pour {what}'
|
'fr_FR': 'J\'attends au moins {upper} argument(s) pour {what}'
|
||||||
|
@ -273,6 +310,7 @@ exports.strings = {
|
||||||
'git-error-no-general-args': {
|
'git-error-no-general-args': {
|
||||||
'__desc__': 'One of the error messages for git',
|
'__desc__': 'One of the error messages for git',
|
||||||
'en_US': 'That command accepts no general arguments',
|
'en_US': 'That command accepts no general arguments',
|
||||||
|
'de_DE': 'Dieser Befehl akzeptiert keine allgemeinen Argumente',
|
||||||
'zh_CN': '该命令不接收参数',
|
'zh_CN': '该命令不接收参数',
|
||||||
'zh_TW': '該指令不接受一般參數',
|
'zh_TW': '該指令不接受一般參數',
|
||||||
'fr_FR': 'Cette commande n\'accepte aucun argument général'
|
'fr_FR': 'Cette commande n\'accepte aucun argument général'
|
||||||
|
@ -281,6 +319,7 @@ exports.strings = {
|
||||||
'copy-tree-string': {
|
'copy-tree-string': {
|
||||||
'__desc__': 'The prompt to copy the tree when sharing',
|
'__desc__': 'The prompt to copy the tree when sharing',
|
||||||
'en_US': 'Copy the tree string below',
|
'en_US': 'Copy the tree string below',
|
||||||
|
'de_DE': 'Kopiere die folgende Baum-Zeichenkette',
|
||||||
'zh_CN': '拷贝下面的树字符串',
|
'zh_CN': '拷贝下面的树字符串',
|
||||||
'zh_TW': '複製下方的樹狀字串',
|
'zh_TW': '複製下方的樹狀字串',
|
||||||
'fr_FR': 'Copiez la chaîne d\'arbre ci-dessous'
|
'fr_FR': 'Copiez la chaîne d\'arbre ci-dessous'
|
||||||
|
@ -289,6 +328,7 @@ exports.strings = {
|
||||||
'learn-git-branching': {
|
'learn-git-branching': {
|
||||||
'__desc__': 'The title of the app, with spaces',
|
'__desc__': 'The title of the app, with spaces',
|
||||||
'en_US': 'Learn Git Branching',
|
'en_US': 'Learn Git Branching',
|
||||||
|
'de_DE': 'Learn Git Branching',
|
||||||
'ja': '日本語版リポジトリ',
|
'ja': '日本語版リポジトリ',
|
||||||
'ko': 'Git 브랜치 배우기',
|
'ko': 'Git 브랜치 배우기',
|
||||||
'zh_CN': '学习Git分支',
|
'zh_CN': '学习Git分支',
|
||||||
|
@ -299,6 +339,7 @@ exports.strings = {
|
||||||
'select-a-level': {
|
'select-a-level': {
|
||||||
'__desc__': 'The prompt to select a level on the drop down view',
|
'__desc__': 'The prompt to select a level on the drop down view',
|
||||||
'en_US': 'Select a level',
|
'en_US': 'Select a level',
|
||||||
|
'de_DE': 'Level auswählen',
|
||||||
'zh_CN': '选择一关',
|
'zh_CN': '选择一关',
|
||||||
'zh_TW': '選擇其中一關',
|
'zh_TW': '選擇其中一關',
|
||||||
'fr_FR': 'Choisissez un niveau'
|
'fr_FR': 'Choisissez un niveau'
|
||||||
|
@ -307,6 +348,7 @@ exports.strings = {
|
||||||
'branch-name-short': {
|
'branch-name-short': {
|
||||||
'__desc__': 'When branch names get too long, we need to truncate them. This is the warning for that',
|
'__desc__': 'When branch names get too long, we need to truncate them. This is the warning for that',
|
||||||
'en_US': 'Sorry, we need to keep branch names short for the visuals. Your branch name was truncated to 9 characters, resulting in "{branch}"',
|
'en_US': 'Sorry, we need to keep branch names short for the visuals. Your branch name was truncated to 9 characters, resulting in "{branch}"',
|
||||||
|
'de_DE': 'Tut mir leid, aber aus Gründen der Darstellung müssen wir die Branch-Namen kurz halten. Dein Branch-Name wurde auf 9 Zeichen gekürzt und heißt daher jetzt "{branch}"',
|
||||||
'zh_CN': '抱歉,为了显示的需要,我们需要一个短些的分支名称。您使用的将被截断到9个字符,即"{branch}"',
|
'zh_CN': '抱歉,为了显示的需要,我们需要一个短些的分支名称。您使用的将被截断到9个字符,即"{branch}"',
|
||||||
'zh_TW': '抱歉,為了顯示的需要,我們需要一個短些的分支名稱。您使用的將被截斷到9个字符,即"{branch}"',
|
'zh_TW': '抱歉,為了顯示的需要,我們需要一個短些的分支名稱。您使用的將被截斷到9个字符,即"{branch}"',
|
||||||
'fr_FR': 'Désolé, nous devons garder les noms de branches courts pour la visualisation. Votre nom de branche a été tronqué à 9 caractères, devenant "{branch}"'
|
'fr_FR': 'Désolé, nous devons garder les noms de branches courts pour la visualisation. Votre nom de branche a été tronqué à 9 caractères, devenant "{branch}"'
|
||||||
|
@ -315,6 +357,7 @@ exports.strings = {
|
||||||
'bad-branch-name': {
|
'bad-branch-name': {
|
||||||
'__desc__': 'When the user enters a branch name thats not ok',
|
'__desc__': 'When the user enters a branch name thats not ok',
|
||||||
'en_US': 'That branch name "{branch}" is not allowed!',
|
'en_US': 'That branch name "{branch}" is not allowed!',
|
||||||
|
'de_DE': 'Der Branch-Name "{branch}" ist nicht erlaubt!',
|
||||||
'zh_CN': '不能给分支起这个名字 "{branch}"',
|
'zh_CN': '不能给分支起这个名字 "{branch}"',
|
||||||
'zh_TW': '不能给分支起這個名字 "{branch}"',
|
'zh_TW': '不能给分支起這個名字 "{branch}"',
|
||||||
'fr_FR': 'Ce nom de branche "{branch}" n\'est pas autorisé'
|
'fr_FR': 'Ce nom de branche "{branch}" n\'est pas autorisé'
|
||||||
|
@ -322,12 +365,14 @@ exports.strings = {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'bad-tag-name': {
|
'bad-tag-name': {
|
||||||
'__desc__': 'When the user enters a tag name thats not ok',
|
'__desc__': 'When the user enters a tag name thats not ok',
|
||||||
'en_US': 'That tag name "{tag}" is not allowed!'
|
'en_US': 'That tag name "{tag}" is not allowed!',
|
||||||
|
'de_DE': 'Der Tag-Name "{tag}" ist nicht erlaubt!'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'option-not-supported': {
|
'option-not-supported': {
|
||||||
'__desc__': 'When the user specifies an option that is not supported by our demo',
|
'__desc__': 'When the user specifies an option that is not supported by our demo',
|
||||||
'en_US': 'The option "{option}" is not supported!',
|
'en_US': 'The option "{option}" is not supported!',
|
||||||
|
'de_DE': 'Die Option "{option}" wird nicht unterstützt!',
|
||||||
'zh_CN': '不支持选项 "{option}"',
|
'zh_CN': '不支持选项 "{option}"',
|
||||||
'zh_TW': '不支援的選項 "{option}"',
|
'zh_TW': '不支援的選項 "{option}"',
|
||||||
'fr_FR': 'L\'option "{option}" n\'est pas supportée'
|
'fr_FR': 'L\'option "{option}" n\'est pas supportée'
|
||||||
|
@ -336,6 +381,7 @@ exports.strings = {
|
||||||
'git-usage-command': {
|
'git-usage-command': {
|
||||||
'__desc__': 'The line that shows how to format a git command',
|
'__desc__': 'The line that shows how to format a git command',
|
||||||
'en_US': 'git <command> [<args>]',
|
'en_US': 'git <command> [<args>]',
|
||||||
|
'de_DE': 'git <Befehl> [<Argumente>]',
|
||||||
'zh_CN': 'git <命令> [<参数>]',
|
'zh_CN': 'git <命令> [<参数>]',
|
||||||
'zh_TW': 'git <指令> [<參數>]',
|
'zh_TW': 'git <指令> [<參數>]',
|
||||||
'fr_FR': 'git <commande> [<arguments>]'
|
'fr_FR': 'git <commande> [<arguments>]'
|
||||||
|
@ -344,6 +390,7 @@ exports.strings = {
|
||||||
'git-supported-commands': {
|
'git-supported-commands': {
|
||||||
'__desc__': 'In the git help command, the header above the supported commands',
|
'__desc__': 'In the git help command, the header above the supported commands',
|
||||||
'en_US': 'Supported commands:',
|
'en_US': 'Supported commands:',
|
||||||
|
'de_DE': 'Unterstützte Befehle:',
|
||||||
'zh_CN': '支持的命令有:',
|
'zh_CN': '支持的命令有:',
|
||||||
'zh_TW': '支援的指令有:',
|
'zh_TW': '支援的指令有:',
|
||||||
'fr_FR': 'Commandes supportées'
|
'fr_FR': 'Commandes supportées'
|
||||||
|
@ -352,6 +399,7 @@ exports.strings = {
|
||||||
'git-usage': {
|
'git-usage': {
|
||||||
'__desc__': 'In the dummy git output, the header before showing all the commands',
|
'__desc__': 'In the dummy git output, the header before showing all the commands',
|
||||||
'en_US': 'Usage:',
|
'en_US': 'Usage:',
|
||||||
|
'de_DE': 'Benutzung:',
|
||||||
'zh_CN': '使用:',
|
'zh_CN': '使用:',
|
||||||
'zh_TW': '用法:',
|
'zh_TW': '用法:',
|
||||||
'fr_FR': 'Utilisation :'
|
'fr_FR': 'Utilisation :'
|
||||||
|
@ -360,14 +408,21 @@ exports.strings = {
|
||||||
'git-version': {
|
'git-version': {
|
||||||
'__desc__': 'The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead',
|
'__desc__': 'The git version dummy output, kind of silly. PCOTTLE is my unix name but feel free to put yours instead',
|
||||||
'en_US': 'Git Version PCOTTLE.1.0',
|
'en_US': 'Git Version PCOTTLE.1.0',
|
||||||
|
'de_DE': 'Git Version PCOTTLE.1.0.jbr',
|
||||||
'zh_CN': 'Git 版本 PCOTTLE.1.0',
|
'zh_CN': 'Git 版本 PCOTTLE.1.0',
|
||||||
'zh_TW': 'Git 版本 PCOTTLE.1.0',
|
'zh_TW': 'Git 版本 PCOTTLE.1.0',
|
||||||
'fr_FR': 'Git version PCOTTLE.1.0'
|
'fr_FR': 'Git version PCOTTLE.1.0'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'flip-tree-command': {
|
||||||
|
'__desc__': 'when the tree is being flipped',
|
||||||
|
'en_US': 'Flipping tree...'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'refresh-tree-command': {
|
'refresh-tree-command': {
|
||||||
'__desc__': 'when the tree is visually refreshed',
|
'__desc__': 'when the tree is visually refreshed',
|
||||||
'en_US': 'Refreshing tree...',
|
'en_US': 'Refreshing tree...',
|
||||||
|
'de_DE': 'Aktualisiere Baum ...',
|
||||||
'zh_CN': '正在刷新树结构...',
|
'zh_CN': '正在刷新树结构...',
|
||||||
'zh_TW': '正在更新樹狀結構……',
|
'zh_TW': '正在更新樹狀結構……',
|
||||||
'fr_FR': 'Actualisation de l\'arbre…'
|
'fr_FR': 'Actualisation de l\'arbre…'
|
||||||
|
@ -376,6 +431,7 @@ exports.strings = {
|
||||||
'locale-command': {
|
'locale-command': {
|
||||||
'__desc__': 'when the locale is set to something',
|
'__desc__': 'when the locale is set to something',
|
||||||
'en_US': 'Locale set to {locale}',
|
'en_US': 'Locale set to {locale}',
|
||||||
|
'de_DE': 'Locale auf {locale} gesetzt',
|
||||||
'zh_CN': '语言更改为 {locale}',
|
'zh_CN': '语言更改为 {locale}',
|
||||||
'zh_TW': '語系設為 {locale}',
|
'zh_TW': '語系設為 {locale}',
|
||||||
'fr_FR': 'Langue changée à {locale}'
|
'fr_FR': 'Langue changée à {locale}'
|
||||||
|
@ -384,6 +440,7 @@ exports.strings = {
|
||||||
'locale-reset-command': {
|
'locale-reset-command': {
|
||||||
'__desc__': 'when the locale is reset',
|
'__desc__': 'when the locale is reset',
|
||||||
'en_US': 'Locale reset to default, which is {locale}',
|
'en_US': 'Locale reset to default, which is {locale}',
|
||||||
|
'de_DE': 'Locale auf Standard zurückgesetzt, also {locale}',
|
||||||
'zh_CN': '语言重置为默认的 {locale}',
|
'zh_CN': '语言重置为默认的 {locale}',
|
||||||
'zh_TW': '還原為預設語系 {locale}',
|
'zh_TW': '還原為預設語系 {locale}',
|
||||||
'fr_FR': 'Langue remise par défaut, qui est {locale}'
|
'fr_FR': 'Langue remise par défaut, qui est {locale}'
|
||||||
|
@ -393,6 +450,7 @@ exports.strings = {
|
||||||
'__desc__': 'command output title from "show"',
|
'__desc__': 'command output title from "show"',
|
||||||
'en_US': 'Please use one of the following commands for more info:',
|
'en_US': 'Please use one of the following commands for more info:',
|
||||||
'zh_TW': '請使用下列其中一個指令取得更多資訊:',
|
'zh_TW': '請使用下列其中一個指令取得更多資訊:',
|
||||||
|
'de_DE': 'Bitte benutze einen der folgenden Befehle um mehr Informationen zu bekommen:',
|
||||||
'fr_FR': 'Merci d\'utiliser une des commandes suivantes pour obtenir plus d\'info'
|
'fr_FR': 'Merci d\'utiliser une des commandes suivantes pour obtenir plus d\'info'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -400,12 +458,14 @@ exports.strings = {
|
||||||
'__desc__': 'command output title from "show commands"',
|
'__desc__': 'command output title from "show commands"',
|
||||||
'en_US': 'Here is a list of all the commmands available:',
|
'en_US': 'Here is a list of all the commmands available:',
|
||||||
'zh_TW': '這份清單列出所有可用指令:',
|
'zh_TW': '這份清單列出所有可用指令:',
|
||||||
|
'de_DE': 'Hier ist eine Liste aller verfügbarer Befehle:',
|
||||||
'fr_FR': 'Ci-dessous est la liste de toutes les commandes disponibles :'
|
'fr_FR': 'Ci-dessous est la liste de toutes les commandes disponibles :'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'cd-command': {
|
'cd-command': {
|
||||||
'__desc__': 'dummy command output for the command in the key',
|
'__desc__': 'dummy command output for the command in the key',
|
||||||
'en_US': 'Directory changed to "/directories/dont/matter/in/this/demo"',
|
'en_US': 'Directory changed to "/directories/dont/matter/in/this/demo"',
|
||||||
|
'de_DE': 'Verzeichnis gewechselt zu "/verzeichnisse/sind/in/dieser/demo/latte"',
|
||||||
'zh_CN': '目录切换到 "/directories/dont/matter/in/this/demo"',
|
'zh_CN': '目录切换到 "/directories/dont/matter/in/this/demo"',
|
||||||
'zh_TW': '目錄切換到 "/directories/dont/matter/in/this/demo"',
|
'zh_TW': '目錄切換到 "/directories/dont/matter/in/this/demo"',
|
||||||
'fr_FR': 'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'
|
'fr_FR': 'Répertoire changé à "/directories/dont/matter/in/this/demo" (les répertoires ne servent à rien dans cette démo)'
|
||||||
|
@ -414,6 +474,7 @@ exports.strings = {
|
||||||
'ls-command': {
|
'ls-command': {
|
||||||
'__desc__': 'Dummy command output for the command in the key',
|
'__desc__': 'Dummy command output for the command in the key',
|
||||||
'en_US': 'DontWorryAboutFilesInThisDemo.txt',
|
'en_US': 'DontWorryAboutFilesInThisDemo.txt',
|
||||||
|
'de_DE': 'VergissDateienInDieserDemo.txt',
|
||||||
'zh_CN': 'DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)',
|
'zh_CN': 'DontWorryAboutFilesInThisDemo.txt (译: 在试验里不用担心文件.txt)',
|
||||||
'zh_TW': 'DontWorryAboutFilesInThisDemo.txt(譯註:在試驗裡不用擔心檔案.txt)',
|
'zh_TW': 'DontWorryAboutFilesInThisDemo.txt(譯註:在試驗裡不用擔心檔案.txt)',
|
||||||
'fr_FR': 'DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)'
|
'fr_FR': 'DontWorryAboutFilesInThisDemo.txt (ne vous préoccupez pas des noms de fichier dans cette démo)'
|
||||||
|
@ -421,6 +482,7 @@ exports.strings = {
|
||||||
'mobile-alert': {
|
'mobile-alert': {
|
||||||
'__desc__': 'When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them',
|
'__desc__': 'When someone comes to the site on a mobile device, they can not input commands so this is a nasty alert to tell them',
|
||||||
'en_US': 'LGB can\'t receive input on mobile, visit on desktop! it\'s worth it :D',
|
'en_US': 'LGB can\'t receive input on mobile, visit on desktop! it\'s worth it :D',
|
||||||
|
'de_DE': 'LGB ist nicht mit mobilen Endgeräten kompatibel, nutz es vom Desktop! Es lohnt sich :D',
|
||||||
'zh_CN': '无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D',
|
'zh_CN': '无法在移动设备/平板上调出键盘 :( 请试试桌面版 :D',
|
||||||
'zh_TW': '無法在行動裝置上叫出鍵盤,請改用桌面版!',
|
'zh_TW': '無法在行動裝置上叫出鍵盤,請改用桌面版!',
|
||||||
'fr_FR': 'Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D'
|
'fr_FR': 'Impossible de faire apparaître le clavier sur mobile / tablette :( Essayez de passer sur un ordinateur de bureau :D'
|
||||||
|
@ -429,6 +491,7 @@ exports.strings = {
|
||||||
'share-tree': {
|
'share-tree': {
|
||||||
'__desc__': 'When you export a tree, we want you to share the tree with friends',
|
'__desc__': 'When you export a tree, we want you to share the tree with friends',
|
||||||
'en_US': 'Share this tree with friends! They can load it with "import tree"',
|
'en_US': 'Share this tree with friends! They can load it with "import tree"',
|
||||||
|
'de_DE': 'Teile diesen git-Baum mit Freunden! Sie können ihn mit "import tree" laden',
|
||||||
'zh_CN': '与你的好友分享提交树!他们可以用 "import tree" 加载它',
|
'zh_CN': '与你的好友分享提交树!他们可以用 "import tree" 加载它',
|
||||||
'zh_TW': '與你的好友分享提交樹!他們可以用 "import tree" 加載它',
|
'zh_TW': '與你的好友分享提交樹!他們可以用 "import tree" 加載它',
|
||||||
'fr_FR': 'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'
|
'fr_FR': 'Partagez cet arbre avec vos amis ! Ils peuvent le charger avec "import tree"'
|
||||||
|
@ -437,6 +500,7 @@ exports.strings = {
|
||||||
'paste-json': {
|
'paste-json': {
|
||||||
'__desc__': 'When you are importing a level or tree',
|
'__desc__': 'When you are importing a level or tree',
|
||||||
'en_US': 'Paste a JSON blob below!',
|
'en_US': 'Paste a JSON blob below!',
|
||||||
|
'de_DE': 'Füg einen JSON-Blob unten ein!',
|
||||||
'zh_CN': '在下边粘贴一个JSON串',
|
'zh_CN': '在下边粘贴一个JSON串',
|
||||||
'zh_TW': '在下方貼上一串 JSON',
|
'zh_TW': '在下方貼上一串 JSON',
|
||||||
'fr_FR': 'Collez un blob JSON ci-dessous !'
|
'fr_FR': 'Collez un blob JSON ci-dessous !'
|
||||||
|
@ -445,6 +509,7 @@ exports.strings = {
|
||||||
'solved-map-reset': {
|
'solved-map-reset': {
|
||||||
'__desc__': 'When you reset the solved map to clear your solved history, in case someone else wants to use your browser',
|
'__desc__': 'When you reset the solved map to clear your solved history, in case someone else wants to use your browser',
|
||||||
'en_US': 'Solved map was reset, you are starting from a clean slate!',
|
'en_US': 'Solved map was reset, you are starting from a clean slate!',
|
||||||
|
'de_DE': 'Gelöste Karte wurde zurückgesetzt, du fängst mit einem leeren Blatt an!',
|
||||||
'zh_CN': '解决列表已重置,您现在从零开始了',
|
'zh_CN': '解决列表已重置,您现在从零开始了',
|
||||||
'zh_TW': '解決列表已重置,您現在從零開始了',
|
'zh_TW': '解決列表已重置,您現在從零開始了',
|
||||||
'fr_FR': 'La carte des niveaux résolus a été effacée, vous repartez de zéro !'
|
'fr_FR': 'La carte des niveaux résolus a été effacée, vous repartez de zéro !'
|
||||||
|
@ -453,6 +518,7 @@ exports.strings = {
|
||||||
'level-cant-exit': {
|
'level-cant-exit': {
|
||||||
'__desc__': 'When the user tries to exit a level when they are not in one',
|
'__desc__': 'When the user tries to exit a level when they are not in one',
|
||||||
'en_US': 'You are not in a level! You are in a sandbox, start a level with "levels"',
|
'en_US': 'You are not in a level! You are in a sandbox, start a level with "levels"',
|
||||||
|
'de_DE': 'Du bist nicht in einem Level! Du bist im Sandkasten-Modus, starte einen Level mit "levels"',
|
||||||
'zh_CN': '您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',
|
'zh_CN': '您没在关卡中!您在沙盒中,要开始关卡请输入 "levels"',
|
||||||
'zh_TW': '您沒在關卡中!您在沙盒中,要開始關卡請輸入 "levels"',
|
'zh_TW': '您沒在關卡中!您在沙盒中,要開始關卡請輸入 "levels"',
|
||||||
'fr_FR': 'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'
|
'fr_FR': 'Vous n\'êtes pas dans un niveau ! Vous êtes dans le mode bac à sable, commencez un niveau avec "levels"'
|
||||||
|
@ -461,6 +527,7 @@ exports.strings = {
|
||||||
'level-no-id': {
|
'level-no-id': {
|
||||||
'__desc__': 'When you say an id but that level doesnt exist',
|
'__desc__': 'When you say an id but that level doesnt exist',
|
||||||
'en_US': 'A level for that id "{id}" was not found! Opening up a level selection view',
|
'en_US': 'A level for that id "{id}" was not found! Opening up a level selection view',
|
||||||
|
'de_DE': 'Konnte keinen Level mit der ID "{id}" finden! Öffne einen Level-Auswahldialog',
|
||||||
'zh_CN': '没找到id为 "{id}" 的关卡!打开关卡选择框',
|
'zh_CN': '没找到id为 "{id}" 的关卡!打开关卡选择框',
|
||||||
'zh_TW': '找不到 id 為 "{id}" 的關卡!開啟關卡選擇視窗',
|
'zh_TW': '找不到 id 為 "{id}" 的關卡!開啟關卡選擇視窗',
|
||||||
'fr_FR': 'Le niveau dont l\'identifiant est {id} n\'a pas été trouvé ! Ouverture de la vue de sélection des niveaux'
|
'fr_FR': 'Le niveau dont l\'identifiant est {id} n\'a pas été trouvé ! Ouverture de la vue de sélection des niveaux'
|
||||||
|
@ -469,6 +536,7 @@ exports.strings = {
|
||||||
'undo-stack-empty': {
|
'undo-stack-empty': {
|
||||||
'__desc__': 'The undo command can only undo back until the last time the level was reset or the beginning of the level',
|
'__desc__': 'The undo command can only undo back until the last time the level was reset or the beginning of the level',
|
||||||
'en_US': 'The undo stack is empty!',
|
'en_US': 'The undo stack is empty!',
|
||||||
|
'de_DE': 'Die Undo-Liste ist leer!',
|
||||||
'zh_CN': '还没有什么可以撤销',
|
'zh_CN': '还没有什么可以撤销',
|
||||||
'zh_TW': '還沒有什麼可以撤銷',
|
'zh_TW': '還沒有什麼可以撤銷',
|
||||||
'fr_FR': 'La pile d\'annulation est vide !'
|
'fr_FR': 'La pile d\'annulation est vide !'
|
||||||
|
@ -477,6 +545,7 @@ exports.strings = {
|
||||||
'already-solved': {
|
'already-solved': {
|
||||||
'__desc__': 'When you play in a level that is already solved',
|
'__desc__': 'When you play in a level that is already solved',
|
||||||
'en_US': 'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',
|
'en_US': 'You have already solved this level, try other levels with "levels" or go back to sandbox with "sandbox"',
|
||||||
|
'de_DE': 'Du hast diesen Level bereits gelöst, probier einen anderen Level mit "levels" aus oder geh in den Sandkasten-Modus mit "sandbox"',
|
||||||
'zh_CN': '你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',
|
'zh_CN': '你已经解决了本关,输入 "levels" 尝试其他关卡,或者输入 "sandbox" 回到沙盒中',
|
||||||
'zh_TW': '你已經解决了本關,輸入 "levels" 嘗試其他關卡,或者輸入 "sandbox" 回到沙盒中',
|
'zh_TW': '你已經解决了本關,輸入 "levels" 嘗試其他關卡,或者輸入 "sandbox" 回到沙盒中',
|
||||||
'fr_FR': 'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'
|
'fr_FR': 'Vous avez déjà résolu ce niveau, essayez d\'autres niveaux avec "levels" ou revenez au bac à sable avec "sandbox"'
|
||||||
|
@ -485,6 +554,7 @@ exports.strings = {
|
||||||
'command-disabled': {
|
'command-disabled': {
|
||||||
'__desc__': 'When you try a command that is disabled',
|
'__desc__': 'When you try a command that is disabled',
|
||||||
'en_US': 'That git command is disabled for this level!',
|
'en_US': 'That git command is disabled for this level!',
|
||||||
|
'de_DE': 'Dieser git-Befehl ist für diesen Level deaktiviert!',
|
||||||
'zh_CN': '该命令在本关不允许使用!',
|
'zh_CN': '该命令在本关不允许使用!',
|
||||||
'zh_TW': '本關禁止使用該 git 指令!',
|
'zh_TW': '本關禁止使用該 git 指令!',
|
||||||
'fr_FR': 'Cette commande git est désactivée pour ce niveau !'
|
'fr_FR': 'Cette commande git est désactivée pour ce niveau !'
|
||||||
|
@ -493,6 +563,7 @@ exports.strings = {
|
||||||
'share-json': {
|
'share-json': {
|
||||||
'__desc__': 'when you have made the level, prompt to share this',
|
'__desc__': 'when you have made the level, prompt to share this',
|
||||||
'en_US': 'Here is the JSON for this level! Share it with somenoe or send it to me on Github',
|
'en_US': 'Here is the JSON for this level! Share it with somenoe or send it to me on Github',
|
||||||
|
'de_DE': 'Hier ist das JSON für diesen Level! Teil es mit jemandem or schick es mir über Github',
|
||||||
'zh_CN': '这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上',
|
'zh_CN': '这是一个关卡定义JSON!您可以分享它或者发到我的GitHub上',
|
||||||
'zh_TW': '這是本關的 JSON!您可以分享給別人,或是送到 Github 上給我',
|
'zh_TW': '這是本關的 JSON!您可以分享給別人,或是送到 Github 上給我',
|
||||||
'fr_FR': 'Voici le JSON pour ce niveau ! Partagez-le avec quelqu\'un ou envoyez-le moi sur Github'
|
'fr_FR': 'Voici le JSON pour ce niveau ! Partagez-le avec quelqu\'un ou envoyez-le moi sur Github'
|
||||||
|
@ -501,6 +572,7 @@ exports.strings = {
|
||||||
'want-start-dialog': {
|
'want-start-dialog': {
|
||||||
'__desc__': 'prompt to add a start dialog',
|
'__desc__': 'prompt to add a start dialog',
|
||||||
'en_US': 'You have not specified a start dialog, would you like to add one?',
|
'en_US': 'You have not specified a start dialog, would you like to add one?',
|
||||||
|
'de_DE': 'Du hast noch keinen Einführungs-Dialog geschrieben, willst du einen hinzufügen?',
|
||||||
'zh_CN': '您还没有定义一开始的介绍,是否添加一个?',
|
'zh_CN': '您还没有定义一开始的介绍,是否添加一个?',
|
||||||
'zh_TW': '尚未指定開始對話視窗,是否立即新增?',
|
'zh_TW': '尚未指定開始對話視窗,是否立即新增?',
|
||||||
'fr_FR': 'Vous n\'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?'
|
'fr_FR': 'Vous n\'avez pas spécifié de dialogue de départ, voulez-vous en ajouter un ?'
|
||||||
|
@ -509,6 +581,7 @@ exports.strings = {
|
||||||
'want-hint': {
|
'want-hint': {
|
||||||
'__desc__': 'prompt to add a hint',
|
'__desc__': 'prompt to add a hint',
|
||||||
'en_US': 'You have not specified a hint, would you like to add one?',
|
'en_US': 'You have not specified a hint, would you like to add one?',
|
||||||
|
'de_DE': 'Du hast noch keinen Hinweis geschrieben, magst du einen hinzufügen?',
|
||||||
'zh_CN': '您还没有定义提示,是否添加一个?',
|
'zh_CN': '您还没有定义提示,是否添加一个?',
|
||||||
'zh_TW': '尚未指定提示,是否立即新增?',
|
'zh_TW': '尚未指定提示,是否立即新增?',
|
||||||
'fr_FR': 'Vous n\'avez pas spécifié d\'indice, voulez-vous en ajouter un ?'
|
'fr_FR': 'Vous n\'avez pas spécifié d\'indice, voulez-vous en ajouter un ?'
|
||||||
|
@ -517,6 +590,7 @@ exports.strings = {
|
||||||
'prompt-hint': {
|
'prompt-hint': {
|
||||||
'__desc__': 'prompt for hint',
|
'__desc__': 'prompt for hint',
|
||||||
'en_US': 'Enter the hint for this level, or leave this blank if you do not want to include one',
|
'en_US': 'Enter the hint for this level, or leave this blank if you do not want to include one',
|
||||||
|
'de_DE': 'Gib den Hinweis für diesen Level an, oder lass es leer wenn du keinen hinzufügen willst',
|
||||||
'zh_CN': '请输入关卡提示,或者故意留空',
|
'zh_CN': '请输入关卡提示,或者故意留空',
|
||||||
'zh_TW': '請輸入關卡提示,或者故意留空',
|
'zh_TW': '請輸入關卡提示,或者故意留空',
|
||||||
'fr_FR': 'Entrez l\'indice pour ce niveau, ou laissez-le vide pour ne pas l\'inclure'
|
'fr_FR': 'Entrez l\'indice pour ce niveau, ou laissez-le vide pour ne pas l\'inclure'
|
||||||
|
@ -525,6 +599,7 @@ exports.strings = {
|
||||||
'prompt-name': {
|
'prompt-name': {
|
||||||
'__desc__': 'prompt for level name',
|
'__desc__': 'prompt for level name',
|
||||||
'en_US': 'Enter the name for the level',
|
'en_US': 'Enter the name for the level',
|
||||||
|
'de_DE': 'Gib den Namen für diesen Level an',
|
||||||
'zh_CN': '输入关卡名',
|
'zh_CN': '输入关卡名',
|
||||||
'zh_TW': '請輸入關卡名稱',
|
'zh_TW': '請輸入關卡名稱',
|
||||||
'fr_FR': 'Entrez le nom pour ce niveau'
|
'fr_FR': 'Entrez le nom pour ce niveau'
|
||||||
|
@ -533,6 +608,7 @@ exports.strings = {
|
||||||
'solution-empty': {
|
'solution-empty': {
|
||||||
'__desc__': 'If you define a solution without any commands, aka a level that is solved without doing anything',
|
'__desc__': 'If you define a solution without any commands, aka a level that is solved without doing anything',
|
||||||
'en_US': 'Your solution is empty!! Something is amiss',
|
'en_US': 'Your solution is empty!! Something is amiss',
|
||||||
|
'de_DE': 'Deine Auflösung ist leer! Hier fehlt etwas',
|
||||||
'zh_CN': '你的解法是空的!! 这应该是出错了',
|
'zh_CN': '你的解法是空的!! 这应该是出错了',
|
||||||
'zh_TW': '您的解法是空的!這一定是哪裡出錯了',
|
'zh_TW': '您的解法是空的!這一定是哪裡出錯了',
|
||||||
'fr_FR': 'Votre solution est vide !! Quelque chose ne tourne pas rond'
|
'fr_FR': 'Votre solution est vide !! Quelque chose ne tourne pas rond'
|
||||||
|
@ -541,6 +617,7 @@ exports.strings = {
|
||||||
'define-start-warning': {
|
'define-start-warning': {
|
||||||
'__desc__': 'When you define the start point again, it overwrites the solution and goal so we add a warning',
|
'__desc__': 'When you define the start point again, it overwrites the solution and goal so we add a warning',
|
||||||
'en_US': 'Defining start point... solution and goal will be overwritten if they were defined earlier',
|
'en_US': 'Defining start point... solution and goal will be overwritten if they were defined earlier',
|
||||||
|
'de_DE': 'Lege Start fest ... Auflösung und Ziel werden gelößcht, falls sie schon festgelegt worden waren',
|
||||||
'zh_CN': '定义开始点... 解决方法和目标会被新的替代',
|
'zh_CN': '定义开始点... 解决方法和目标会被新的替代',
|
||||||
'zh_TW': '正在定義起始點……先前定義的解法和目標會被覆蓋掉',
|
'zh_TW': '正在定義起始點……先前定義的解法和目標會被覆蓋掉',
|
||||||
'fr_FR': 'Redéfinition du point de départ… la solution et la cible seront écrasés s\'ils ont déjà été définis'
|
'fr_FR': 'Redéfinition du point de départ… la solution et la cible seront écrasés s\'ils ont déjà été définis'
|
||||||
|
@ -549,6 +626,7 @@ exports.strings = {
|
||||||
'help-vague-level': {
|
'help-vague-level': {
|
||||||
'__desc__': 'When you are in a level and you say help, its vague and you need to specify',
|
'__desc__': 'When you are in a level and you say help, its vague and you need to specify',
|
||||||
'en_US': 'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',
|
'en_US': 'You are in a level, so multiple forms of help are available. Please select either "help level" to learn more about this lesson, "help general" for using Learn GitBranching, or "objective" to learn about how to solve the level.',
|
||||||
|
'de_DE': 'Du befindest dich in einem Level, daher gibt es verschiedene Hilfen. Gib "help level" ein um mehr úber diesen Level zu erfahren, "help general" um zu sehen wie Learn Git Branching bedient wird, oder "objective" um das Ziel dieses Levels zu erfahren.',
|
||||||
'zh_CN': '您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',
|
'zh_CN': '您正在关卡中,这里有多种形式的帮助,请选择 "help level" (关卡帮助)或 "help general" (一般帮助)',
|
||||||
'zh_TW': '您正在關卡中,這裡有多種形式的幫助,請選擇 "help level" (關卡幫助)或 "help general" (一般幫助)',
|
'zh_TW': '您正在關卡中,這裡有多種形式的幫助,請選擇 "help level" (關卡幫助)或 "help general" (一般幫助)',
|
||||||
'fr_FR': 'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'
|
'fr_FR': 'Vous êtes dans un niveau, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help level" pour en apprendre plus sur cette leçon, "help general" pour l\'utilisation de Learn GitBranching, ou "objective" pour apprendre comment résoudre le niveau'
|
||||||
|
@ -557,14 +635,26 @@ exports.strings = {
|
||||||
'help-vague-builder': {
|
'help-vague-builder': {
|
||||||
'__desc__': 'When you are in a level builder, the help command is vague so you need to specify what you mean',
|
'__desc__': 'When you are in a level builder, the help command is vague so you need to specify what you mean',
|
||||||
'en_US': 'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',
|
'en_US': 'You are in a level builder, so multiple forms of help are available. Please select either "help general" or "help builder"',
|
||||||
|
'de_DE': 'Du befindest dich im Level-Editor, daher gibt es verschiedene Hilfen. Gib bitte "help general" oder "help builder" ein',
|
||||||
'zh_CN': '您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',
|
'zh_CN': '您正在进行关卡构建中,这里有多种形式的帮助,请选择 "help general" (一般帮助)或 "help builder" (关卡构建帮助)',
|
||||||
'zh_TW': '您正在進行關卡構建中,這裡有多種形式的幫助,請選擇 "help general" (一般幫助)或 "help builder" (關卡構建幫助)',
|
'zh_TW': '您正在進行關卡構建中,這裡有多種形式的幫助,請選擇 "help general" (一般幫助)或 "help builder" (關卡構建幫助)',
|
||||||
'fr_FR': 'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'
|
'fr_FR': 'Vous êtes dans l\'éditeur de niveaux, donc plusieurs formes d\'aide sont disponibles. Merci de sélectionner soit "help general" soit "help builder"'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'show-goal-button': {
|
||||||
|
'__desc__': 'button label to show goal',
|
||||||
|
'en_US': 'Show Goal'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
'hide-goal-button': {
|
||||||
|
'__desc__': 'button label to hide goal',
|
||||||
|
'en_US': 'Hide Goal'
|
||||||
|
},
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'goal-to-reach': {
|
'goal-to-reach': {
|
||||||
'__desc__': 'title of window that shoes the goal tree to reach',
|
'__desc__': 'title of window that shoes the goal tree to reach',
|
||||||
'en_US': 'Goal To Reach',
|
'en_US': 'Goal To Reach',
|
||||||
|
'de_DE': 'Ziel',
|
||||||
'zh_CN': '目标',
|
'zh_CN': '目标',
|
||||||
'zh_TW': '目標',
|
'zh_TW': '目標',
|
||||||
'fr_FR': 'Cible à atteindre'
|
'fr_FR': 'Cible à atteindre'
|
||||||
|
@ -572,12 +662,14 @@ exports.strings = {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'goal-only-master': {
|
'goal-only-master': {
|
||||||
'__desc__': 'the helper message for the window that shows the goal tree when the goal will only be compared using the master branch',
|
'__desc__': 'the helper message for the window that shows the goal tree when the goal will only be compared using the master branch',
|
||||||
'en_US': '<span class="fwber">Note:</span> Only the master branch will be checked in this level. The other branches are simply for reference (shown as dashed labels below). As always, you can hide this dialog with "hide goal"'
|
'en_US': '<span class="fwber">Note:</span> Only the master branch will be checked in this level. The other branches are simply for reference (shown as dashed labels below). As always, you can hide this dialog with "hide goal"',
|
||||||
|
'de_DE': '<span class="fwber">Hinweis:</span> In diesem Level wird nur der Branch master geprüft. Die anderen Branches dienen nur als Vergleichsbasis (als gestrichelte Bezeichner dargestellt). Wie immer kannst du diese Meldung mit "hide goal" ausblenden'
|
||||||
},
|
},
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
'hide-goal': {
|
'hide-goal': {
|
||||||
'__desc__': 'the helper message for the window that shows the goal tree',
|
'__desc__': 'the helper message for the window that shows the goal tree',
|
||||||
'en_US': 'You can hide this window with "hide goal"',
|
'en_US': 'You can hide this window with "hide goal"',
|
||||||
|
'de_DE': 'Du kannst diese Meldung mit "hide goal" ausblenden',
|
||||||
'zh_CN': '你可以通过命令 "hide goal" 关闭这个窗口',
|
'zh_CN': '你可以通过命令 "hide goal" 关闭这个窗口',
|
||||||
'zh_TW': '你可以通過命令 "hide goal" 關閉這個窗口',
|
'zh_TW': '你可以通過命令 "hide goal" 關閉這個窗口',
|
||||||
'fr_FR': 'Vous pouvez masquer cette fenêtre avec "hide goal"'
|
'fr_FR': 'Vous pouvez masquer cette fenêtre avec "hide goal"'
|
||||||
|
@ -586,6 +678,7 @@ exports.strings = {
|
||||||
'hide-start': {
|
'hide-start': {
|
||||||
'__desc__': 'The helper message for the window that shows the start tree for a level',
|
'__desc__': 'The helper message for the window that shows the start tree for a level',
|
||||||
'en_US': 'You can hide this window with "hide start"',
|
'en_US': 'You can hide this window with "hide start"',
|
||||||
|
'de_DE': 'Du kannst diese Meldung mit "hide start" ausblenden',
|
||||||
'zh_CN': '你可以通过命令 "hide start" 关闭这个窗口',
|
'zh_CN': '你可以通过命令 "hide start" 关闭这个窗口',
|
||||||
'zh_TW': '你可以通過命令 "hide start" 關閉這個窗口',
|
'zh_TW': '你可以通過命令 "hide start" 關閉這個窗口',
|
||||||
'fr_FR': 'Vous pouvez masquer cette fenêtre avec "hide start"'
|
'fr_FR': 'Vous pouvez masquer cette fenêtre avec "hide start"'
|
||||||
|
@ -594,6 +687,7 @@ exports.strings = {
|
||||||
'level-builder': {
|
'level-builder': {
|
||||||
'__desc__': 'The name for the environment where you build levels',
|
'__desc__': 'The name for the environment where you build levels',
|
||||||
'en_US': 'Level Builder',
|
'en_US': 'Level Builder',
|
||||||
|
'de_DE': 'Level-Editor',
|
||||||
'zh_CN': '关卡生成器',
|
'zh_CN': '关卡生成器',
|
||||||
'zh_TW': '關卡產生器',
|
'zh_TW': '關卡產生器',
|
||||||
'fr_FR': 'Éditeur de niveaux'
|
'fr_FR': 'Éditeur de niveaux'
|
||||||
|
@ -602,6 +696,7 @@ exports.strings = {
|
||||||
'no-start-dialog': {
|
'no-start-dialog': {
|
||||||
'__desc__': 'when the user tries to open a start dialog for a level that does not have one',
|
'__desc__': 'when the user tries to open a start dialog for a level that does not have one',
|
||||||
'en_US': 'There is no start dialog to show for this level!',
|
'en_US': 'There is no start dialog to show for this level!',
|
||||||
|
'de_DE': 'Es gibt keinen Einführungs-Dialog für diesen Level!',
|
||||||
'zh_CN': '介绍? 这关真没有!',
|
'zh_CN': '介绍? 这关真没有!',
|
||||||
'zh_TW': '介紹? 這關真沒有!',
|
'zh_TW': '介紹? 這關真沒有!',
|
||||||
'fr_FR': 'Il n\'y a aucun dialogue de départ à afficher pour ce niveau !'
|
'fr_FR': 'Il n\'y a aucun dialogue de départ à afficher pour ce niveau !'
|
||||||
|
@ -610,6 +705,7 @@ exports.strings = {
|
||||||
'no-hint': {
|
'no-hint': {
|
||||||
'__desc__': 'when no hint is available for a level',
|
'__desc__': 'when no hint is available for a level',
|
||||||
'en_US': "Hmm, there doesn't seem to be a hint for this level :-/",
|
'en_US': "Hmm, there doesn't seem to be a hint for this level :-/",
|
||||||
|
'de_DE': "Hm, es gibt anscheinend keinen Hinweis für diesen Level :-/",
|
||||||
'zh_CN': "提示?嗯,这关真没有哎~ :-/",
|
'zh_CN': "提示?嗯,这关真没有哎~ :-/",
|
||||||
'zh_TW': "提示?嗯,這關真沒有哎~ :-/",
|
'zh_TW': "提示?嗯,這關真沒有哎~ :-/",
|
||||||
'fr_FR': 'Hum, il ne semble pas y avoir d\'indice pour ce niveau :-/'
|
'fr_FR': 'Hum, il ne semble pas y avoir d\'indice pour ce niveau :-/'
|
||||||
|
@ -618,6 +714,7 @@ exports.strings = {
|
||||||
'error-untranslated-key': {
|
'error-untranslated-key': {
|
||||||
'__desc__': 'This error happens when we are trying to translate a specific key and the locale version is mission',
|
'__desc__': 'This error happens when we are trying to translate a specific key and the locale version is mission',
|
||||||
'en_US': 'The translation for {key} does not exist yet :( Please hop on github and offer up a translation!',
|
'en_US': 'The translation for {key} does not exist yet :( Please hop on github and offer up a translation!',
|
||||||
|
'de_DE': 'Die Übersetzung für {key} existiert noch nicht :( Falls du eine hast, bitte teil sie mit auf Github mit!',
|
||||||
'zh_CN': '还没翻译 {key} :( 请在gitHub上贡献你的翻译!',
|
'zh_CN': '还没翻译 {key} :( 请在gitHub上贡献你的翻译!',
|
||||||
'zh_TW': '還沒翻譯 {key} :( 請在gitHub上貢獻你的翻譯!',
|
'zh_TW': '還沒翻譯 {key} :( 請在gitHub上貢獻你的翻譯!',
|
||||||
'fr_FR': 'La traduction pour {key} n\'existe pas encore :( Venez sur Github pour en offrir une !'
|
'fr_FR': 'La traduction pour {key} n\'existe pas encore :( Venez sur Github pour en offrir une !'
|
||||||
|
@ -626,6 +723,7 @@ exports.strings = {
|
||||||
'error-untranslated': {
|
'error-untranslated': {
|
||||||
'__desc__': 'The general error when we encounter a dialog that is not translated',
|
'__desc__': 'The general error when we encounter a dialog that is not translated',
|
||||||
'en_US': 'This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!',
|
'en_US': 'This dialog or text is not yet translated in your locale :( Hop on github to aid in translation!',
|
||||||
|
'de_DE': 'Dieser Dialog oder Text ist noch nicht in deine Sprache übersetzt. :( Schau auf Github vorbei um bei der Übersetzung zu helfen!',
|
||||||
'zh_CN': '这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!',
|
'zh_CN': '这段对话还没有被翻译成你的语言 :( 欢迎在gitHub上贡献你的翻译!',
|
||||||
'zh_TW': '這段對話尚未翻成您的語言 :( 歡迎到 github 貢獻翻譯!',
|
'zh_TW': '這段對話尚未翻成您的語言 :( 歡迎到 github 貢獻翻譯!',
|
||||||
'fr_FR': 'Ce message n\'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !'
|
'fr_FR': 'Ce message n\'a pas encore été traduit dans votre langue :( Venez sur Github aider à la traduction !'
|
||||||
|
|
|
@ -10,6 +10,7 @@ var log = require('../log');
|
||||||
var Errors = require('../util/errors');
|
var Errors = require('../util/errors');
|
||||||
var Sandbox = require('../sandbox/').Sandbox;
|
var Sandbox = require('../sandbox/').Sandbox;
|
||||||
var Constants = require('../util/constants');
|
var Constants = require('../util/constants');
|
||||||
|
var GlobalState = require('../util/globalState');
|
||||||
|
|
||||||
var Visualization = require('../visuals/visualization').Visualization;
|
var Visualization = require('../visuals/visualization').Visualization;
|
||||||
var ParseWaterfall = require('../level/parseWaterfall').ParseWaterfall;
|
var ParseWaterfall = require('../level/parseWaterfall').ParseWaterfall;
|
||||||
|
@ -49,6 +50,9 @@ var Level = Sandbox.extend({
|
||||||
|
|
||||||
this.initGoalData(options);
|
this.initGoalData(options);
|
||||||
this.initName(options);
|
this.initName(options);
|
||||||
|
this.on('toggleGoal', this.toggleGoal);
|
||||||
|
this.on('minimizeCanvas', this.minimizeGoal);
|
||||||
|
this.on('resizeCanvas', this.resizeGoal);
|
||||||
|
|
||||||
Level.__super__.initialize.apply(this, [options]);
|
Level.__super__.initialize.apply(this, [options]);
|
||||||
this.startOffCommand();
|
this.startOffCommand();
|
||||||
|
@ -127,7 +131,8 @@ var Level = Sandbox.extend({
|
||||||
var name = intl.getName(this.level);
|
var name = intl.getName(this.level);
|
||||||
|
|
||||||
this.levelToolbar = new LevelToolbar({
|
this.levelToolbar = new LevelToolbar({
|
||||||
name: name
|
name: name,
|
||||||
|
parent: this
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -169,7 +174,8 @@ var Level = Sandbox.extend({
|
||||||
var onlyMaster = TreeCompare.onlyMasterCompared(this.level);
|
var onlyMaster = TreeCompare.onlyMasterCompared(this.level);
|
||||||
// first we make the goal visualization holder
|
// first we make the goal visualization holder
|
||||||
this.goalCanvasHolder = new CanvasTerminalHolder({
|
this.goalCanvasHolder = new CanvasTerminalHolder({
|
||||||
text: (onlyMaster) ? intl.str('goal-only-master') : undefined
|
text: (onlyMaster) ? intl.str('goal-only-master') : undefined,
|
||||||
|
parent: this
|
||||||
});
|
});
|
||||||
|
|
||||||
// then we make a visualization. the "el" here is the element to
|
// then we make a visualization. the "el" here is the element to
|
||||||
|
@ -184,9 +190,42 @@ var Level = Sandbox.extend({
|
||||||
levelBlob: this.level,
|
levelBlob: this.level,
|
||||||
noClick: true
|
noClick: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If the goal visualization gets dragged to the right side of the screen, then squeeze the main
|
||||||
|
// repo visualization a bit to make room. This way, you could have the goal window hang out on
|
||||||
|
// the right side of the screen and still see the repo visualization.
|
||||||
|
this.goalVis.customEvents.on('drag', _.bind(function(event, ui) {
|
||||||
|
if (ui.position.left > 0.5 * $(window).width()) {
|
||||||
|
if (!$('#goalPlaceholder').is(':visible')) {
|
||||||
|
$('#goalPlaceholder').show();
|
||||||
|
this.mainVis.myResize();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($('#goalPlaceholder').is(':visible')) {
|
||||||
|
$('#goalPlaceholder').hide();
|
||||||
|
this.mainVis.myResize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this));
|
||||||
|
|
||||||
return this.goalCanvasHolder;
|
return this.goalCanvasHolder;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
minimizeGoal: function (position, size) {
|
||||||
|
this.goalVis.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();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
resizeGoal: function () {
|
||||||
|
this.goalVis.myResize();
|
||||||
|
},
|
||||||
|
|
||||||
showSolution: function(command, deferred) {
|
showSolution: function(command, deferred) {
|
||||||
var toIssue = this.level.solutionCommand;
|
var toIssue = this.level.solutionCommand;
|
||||||
var issueFunc = _.bind(function() {
|
var issueFunc = _.bind(function() {
|
||||||
|
@ -229,8 +268,22 @@ var Level = Sandbox.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggleGoal: function () {
|
||||||
|
if (this.goalCanvasHolder && this.goalCanvasHolder.inDom) {
|
||||||
|
this.hideGoal();
|
||||||
|
} else {
|
||||||
|
this.showGoal();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
showGoal: function(command, defer) {
|
showGoal: function(command, defer) {
|
||||||
this.showSideVis(command, defer, this.goalCanvasHolder, this.initGoalVisualization);
|
this.showSideVis(command, defer, this.goalCanvasHolder, this.initGoalVisualization);
|
||||||
|
this.levelToolbar.$goalButton.text(intl.str('hide-goal-button'));
|
||||||
|
// show the squeezer again we are to the side
|
||||||
|
if ($(this.goalVis.el).offset().left > 0.5 * $(window).width()) {
|
||||||
|
$('#goalPlaceholder').show();
|
||||||
|
this.mainVis.myResize();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showSideVis: function(command, defer, canvasHolder, initMethod) {
|
showSideVis: function(command, defer, canvasHolder, initMethod) {
|
||||||
|
@ -241,12 +294,13 @@ var Level = Sandbox.extend({
|
||||||
canvasHolder = initMethod.apply(this);
|
canvasHolder = initMethod.apply(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasHolder.slideIn();
|
canvasHolder.restore(this.goalWindowPos, this.goalWindowSize);
|
||||||
setTimeout(safeFinish, canvasHolder.getAnimationTime());
|
setTimeout(safeFinish, canvasHolder.getAnimationTime());
|
||||||
},
|
},
|
||||||
|
|
||||||
hideGoal: function(command, defer) {
|
hideGoal: function(command, defer) {
|
||||||
this.hideSideVis(command, defer, this.goalCanvasHolder);
|
this.hideSideVis(command, defer, this.goalCanvasHolder);
|
||||||
|
this.levelToolbar.$goalButton.text(intl.str('show-goal-button'));
|
||||||
},
|
},
|
||||||
|
|
||||||
hideSideVis: function(command, defer, canvasHolder, vis) {
|
hideSideVis: function(command, defer, canvasHolder, vis) {
|
||||||
|
@ -326,7 +380,7 @@ var Level = Sandbox.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var current = this.mainVis.gitEngine.exportTree();
|
var current = this.mainVis.gitEngine.printTree();
|
||||||
var solved = TreeCompare.dispatchFromLevel(this.level, current);
|
var solved = TreeCompare.dispatchFromLevel(this.level, current);
|
||||||
|
|
||||||
if (!solved) {
|
if (!solved) {
|
||||||
|
@ -365,7 +419,7 @@ var Level = Sandbox.extend({
|
||||||
var numCommands = this.gitCommandsIssued.length;
|
var numCommands = this.gitCommandsIssued.length;
|
||||||
var best = this.getNumSolutionCommands();
|
var best = this.getNumSolutionCommands();
|
||||||
|
|
||||||
Constants.GLOBAL.isAnimating = true;
|
GlobalState.isAnimating = true;
|
||||||
var skipFinishDialog = this.testOption('noFinishDialog');
|
var skipFinishDialog = this.testOption('noFinishDialog');
|
||||||
var finishAnimationChain = this.mainVis.gitVisuals.finishAnimation();
|
var finishAnimationChain = this.mainVis.gitVisuals.finishAnimation();
|
||||||
if (this.mainVis.originVis) {
|
if (this.mainVis.originVis) {
|
||||||
|
@ -401,7 +455,7 @@ var Level = Sandbox.extend({
|
||||||
// nothing to do, we will just close
|
// nothing to do, we will just close
|
||||||
})
|
})
|
||||||
.done(function() {
|
.done(function() {
|
||||||
Constants.GLOBAL.isAnimating = false;
|
GlobalState.isAnimating = false;
|
||||||
defer.resolve();
|
defer.resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,6 +2,7 @@ var _ = require('underscore');
|
||||||
var util = require('../util');
|
var util = require('../util');
|
||||||
|
|
||||||
var constants = require('../util/constants');
|
var constants = require('../util/constants');
|
||||||
|
var GlobalState = require('../util/globalState');
|
||||||
var intl = require('../intl');
|
var intl = require('../intl');
|
||||||
|
|
||||||
var Commands = require('../commands');
|
var Commands = require('../commands');
|
||||||
|
@ -23,7 +24,7 @@ var instantCommands = [
|
||||||
});
|
});
|
||||||
}],
|
}],
|
||||||
[/^(locale|locale reset)$/, function(bits) {
|
[/^(locale|locale reset)$/, function(bits) {
|
||||||
constants.GLOBAL.locale = intl.getDefaultLocale();
|
GlobalState.locale = intl.getDefaultLocale();
|
||||||
var Main = require('../app').getEvents().trigger('localeChanged');
|
var Main = require('../app').getEvents().trigger('localeChanged');
|
||||||
|
|
||||||
throw new CommandResult({
|
throw new CommandResult({
|
||||||
|
@ -47,7 +48,7 @@ var instantCommands = [
|
||||||
});
|
});
|
||||||
}],
|
}],
|
||||||
[/^locale (\w+)$/, function(bits) {
|
[/^locale (\w+)$/, function(bits) {
|
||||||
constants.GLOBAL.locale = bits[1];
|
GlobalState.locale = bits[1];
|
||||||
|
|
||||||
var Main = require('../app').getEvents().trigger('localeChanged');
|
var Main = require('../app').getEvents().trigger('localeChanged');
|
||||||
throw new CommandResult({
|
throw new CommandResult({
|
||||||
|
@ -57,6 +58,15 @@ var instantCommands = [
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}],
|
}],
|
||||||
|
[/^flip$/, function() {
|
||||||
|
GlobalState.flipTreeY = !GlobalState.flipTreeY;
|
||||||
|
|
||||||
|
var events = require('../app').getEvents();
|
||||||
|
events.trigger('refreshTree');
|
||||||
|
throw new CommandResult({
|
||||||
|
msg: intl.str('flip-tree-command')
|
||||||
|
});
|
||||||
|
}],
|
||||||
[/^refresh$/, function() {
|
[/^refresh$/, function() {
|
||||||
var events = require('../app').getEvents();
|
var events = require('../app').getEvents();
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,6 @@ var TIME = {
|
||||||
betweenCommandsDelay: 400
|
betweenCommandsDelay: 400
|
||||||
};
|
};
|
||||||
|
|
||||||
// useful for locks, etc
|
|
||||||
var GLOBAL = {
|
|
||||||
isAnimating: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var VIEWPORT = {
|
var VIEWPORT = {
|
||||||
minZoom: 0.55,
|
minZoom: 0.55,
|
||||||
maxZoom: 1.25,
|
maxZoom: 1.25,
|
||||||
|
@ -53,7 +48,6 @@ var GRAPHICS = {
|
||||||
orphanNodeFill: 'hsb(0.5,0.8,0.7)'
|
orphanNodeFill: 'hsb(0.5,0.8,0.7)'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.GLOBAL = GLOBAL;
|
|
||||||
exports.TIME = TIME;
|
exports.TIME = TIME;
|
||||||
exports.GRAPHICS = GRAPHICS;
|
exports.GRAPHICS = GRAPHICS;
|
||||||
exports.VIEWPORT = VIEWPORT;
|
exports.VIEWPORT = VIEWPORT;
|
||||||
|
|
11
src/js/util/globalState.js
Normal file
11
src/js/util/globalState.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/**
|
||||||
|
* Random grab bag of global state variables so we
|
||||||
|
* dont just straight up use window
|
||||||
|
*/
|
||||||
|
|
||||||
|
var GlobalState = {
|
||||||
|
flipTreeY: false,
|
||||||
|
isAnimating: false
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = GlobalState;
|
|
@ -558,6 +558,7 @@ var LevelToolbar = BaseView.extend({
|
||||||
|
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
this.parent = options.parent;
|
||||||
this.JSON = {
|
this.JSON = {
|
||||||
name: options.name || 'Some level! (unknown name)'
|
name: options.name || 'Some level! (unknown name)'
|
||||||
};
|
};
|
||||||
|
@ -565,6 +566,13 @@ var LevelToolbar = BaseView.extend({
|
||||||
this.beforeDestination = $($('#commandLineHistory div.toolbar')[0]);
|
this.beforeDestination = $($('#commandLineHistory div.toolbar')[0]);
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
|
this.$goalButton = this.$el.find('#show-goal');
|
||||||
|
|
||||||
|
var parent = this.parent;
|
||||||
|
this.$goalButton.on('click', function () {
|
||||||
|
parent.trigger('toggleGoal');
|
||||||
|
});
|
||||||
|
|
||||||
if (!options.wait) {
|
if (!options.wait) {
|
||||||
process.nextTick(_.bind(this.show, this));
|
process.nextTick(_.bind(this.show, this));
|
||||||
}
|
}
|
||||||
|
@ -596,6 +604,10 @@ var LevelToolbar = BaseView.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
var HelperBar = BaseView.extend({
|
var HelperBar = BaseView.extend({
|
||||||
|
getClassName: function() {
|
||||||
|
return 'BaseHelperBar';
|
||||||
|
},
|
||||||
|
|
||||||
tagName: 'div',
|
tagName: 'div',
|
||||||
className: 'helperBar transitionAll',
|
className: 'helperBar transitionAll',
|
||||||
template: _.template($('#helper-bar-template').html()),
|
template: _.template($('#helper-bar-template').html()),
|
||||||
|
@ -655,6 +667,7 @@ var HelperBar = BaseView.extend({
|
||||||
items: this.getItems()
|
items: this.getItems()
|
||||||
};
|
};
|
||||||
this.render();
|
this.render();
|
||||||
|
this.$el.addClass(this.getClassName());
|
||||||
this.setupChildren();
|
this.setupChildren();
|
||||||
|
|
||||||
if (!options.wait) {
|
if (!options.wait) {
|
||||||
|
@ -664,6 +677,10 @@ var HelperBar = BaseView.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
var IntlHelperBar = HelperBar.extend({
|
var IntlHelperBar = HelperBar.extend({
|
||||||
|
getClassName: function() {
|
||||||
|
return 'IntlHelperBar';
|
||||||
|
},
|
||||||
|
|
||||||
getItems: function() {
|
getItems: function() {
|
||||||
return [{
|
return [{
|
||||||
text: 'Git Branching',
|
text: 'Git Branching',
|
||||||
|
@ -683,6 +700,9 @@ var IntlHelperBar = HelperBar.extend({
|
||||||
}, {
|
}, {
|
||||||
text: 'français',
|
text: 'français',
|
||||||
id: 'french'
|
id: 'french'
|
||||||
|
}, {
|
||||||
|
text: 'Deutsch',
|
||||||
|
id: 'german'
|
||||||
}, {
|
}, {
|
||||||
icon: 'signout',
|
icon: 'signout',
|
||||||
id: 'exit'
|
id: 'exit'
|
||||||
|
@ -714,7 +734,12 @@ var IntlHelperBar = HelperBar.extend({
|
||||||
this.hide();
|
this.hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
onSimpchineseClick: function() {
|
onGermanClick: function() {
|
||||||
|
this.fireCommand('locale de_DE; levels');
|
||||||
|
this.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
onChineseClick: function() {
|
||||||
this.fireCommand('locale zh_CN; levels');
|
this.fireCommand('locale zh_CN; levels');
|
||||||
this.hide();
|
this.hide();
|
||||||
},
|
},
|
||||||
|
@ -726,10 +751,17 @@ var IntlHelperBar = HelperBar.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
var CommandsHelperBar = HelperBar.extend({
|
var CommandsHelperBar = HelperBar.extend({
|
||||||
|
getClassName: function() {
|
||||||
|
return 'CommandsHelperBar';
|
||||||
|
},
|
||||||
|
|
||||||
getItems: function() {
|
getItems: function() {
|
||||||
return [{
|
return [{
|
||||||
text: 'Levels',
|
text: 'Levels',
|
||||||
id: 'levels'
|
id: 'levels'
|
||||||
|
}, {
|
||||||
|
text: 'Solution',
|
||||||
|
id: 'solution'
|
||||||
}, {
|
}, {
|
||||||
text: 'Reset',
|
text: 'Reset',
|
||||||
id: 'reset'
|
id: 'reset'
|
||||||
|
@ -753,6 +785,10 @@ var CommandsHelperBar = HelperBar.extend({
|
||||||
HelperBar.prototype.fireCommand.apply(this, arguments);
|
HelperBar.prototype.fireCommand.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onSolutionClick: function() {
|
||||||
|
this.fireCommand('show solution');
|
||||||
|
},
|
||||||
|
|
||||||
onObjectiveClick: function() {
|
onObjectiveClick: function() {
|
||||||
this.fireCommand('objective');
|
this.fireCommand('objective');
|
||||||
},
|
},
|
||||||
|
@ -820,6 +856,8 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
|
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
this.parent = options.parent;
|
||||||
|
this.minHeight = options.minHeight || 200;
|
||||||
this.destination = $('body');
|
this.destination = $('body');
|
||||||
this.JSON = {
|
this.JSON = {
|
||||||
title: options.title || intl.str('goal-to-reach'),
|
title: options.title || intl.str('goal-to-reach'),
|
||||||
|
@ -829,6 +867,19 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
this.render();
|
this.render();
|
||||||
this.inDom = true;
|
this.inDom = true;
|
||||||
|
|
||||||
|
this.$terminal = this.$el.find('.terminal-window-holder').first();
|
||||||
|
this.$terminal.height(0.8 * $(window).height());
|
||||||
|
this.$terminal.draggable({
|
||||||
|
cursor: 'move',
|
||||||
|
handle: '.toolbar',
|
||||||
|
containment: '#interfaceWrapper',
|
||||||
|
scroll: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the entire window gets resized such that the terminal is outside the view, then
|
||||||
|
// move it back into the view, and expand/shrink it vertically as necessary.
|
||||||
|
$(window).on('resize', _.debounce(_.bind(this.recalcLayout, this), 300));
|
||||||
|
|
||||||
if (options.additionalClass) {
|
if (options.additionalClass) {
|
||||||
this.$el.addClass(options.additionalClass);
|
this.$el.addClass(options.additionalClass);
|
||||||
}
|
}
|
||||||
|
@ -841,7 +892,7 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
die: function() {
|
die: function() {
|
||||||
this.slideOut();
|
this.minimize();
|
||||||
this.inDom = false;
|
this.inDom = false;
|
||||||
|
|
||||||
setTimeout(_.bind(function() {
|
setTimeout(_.bind(function() {
|
||||||
|
@ -849,16 +900,79 @@ var CanvasTerminalHolder = BaseView.extend({
|
||||||
}, this), this.getAnimationTime());
|
}, this), this.getAnimationTime());
|
||||||
},
|
},
|
||||||
|
|
||||||
slideOut: function() {
|
minimize: function() {
|
||||||
this.slideToggle(true);
|
this.parent.trigger('minimizeCanvas', {
|
||||||
|
left: this.$terminal.css('left'),
|
||||||
|
top: this.$terminal.css('top')
|
||||||
|
}, {
|
||||||
|
width: this.$terminal.css('width'),
|
||||||
|
height: this.$terminal.css('height')
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$terminal.animate({
|
||||||
|
height: '0px',
|
||||||
|
opacity: 0
|
||||||
|
}, this.getAnimationTime());
|
||||||
},
|
},
|
||||||
|
|
||||||
slideIn: function() {
|
restore: function (pos, size) {
|
||||||
this.slideToggle(false);
|
var self = this;
|
||||||
|
pos = pos || { top: this.$terminal.css('top'), left: this.$terminal.css('left') };
|
||||||
|
size = size || { width: this.$terminal.css('width'), height: this.$terminal.css('height') };
|
||||||
|
|
||||||
|
this.$terminal.css({
|
||||||
|
top: pos.top,
|
||||||
|
left: pos.left,
|
||||||
|
width: size.width,
|
||||||
|
height: '0px',
|
||||||
|
opacity: '0'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$terminal.animate({
|
||||||
|
height: size.height,
|
||||||
|
opacity: 1
|
||||||
|
}, this.getAnimationTime(), function() {
|
||||||
|
self.recalcLayout();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
slideToggle: function(value) {
|
recalcLayout: function () {
|
||||||
this.$('div.terminal-window-holder').toggleClass('slideOut', value);
|
// Resize/reposition self based on the size of the browser window.
|
||||||
|
|
||||||
|
var parent = this.parent,
|
||||||
|
leftOffset = 0,
|
||||||
|
topOffset = 0,
|
||||||
|
heightOffset = 0,
|
||||||
|
width = this.$terminal.outerWidth(),
|
||||||
|
height = this.$terminal.outerHeight(),
|
||||||
|
left = this.$terminal.offset().left,
|
||||||
|
top = this.$terminal.offset().top,
|
||||||
|
right = ($(window).width() - (left + width)),
|
||||||
|
bottom = ($(window).height() - (top + height)),
|
||||||
|
minHeight = 0.75 * $(window).height(),
|
||||||
|
maxHeight = 0.95 * $(window).height();
|
||||||
|
|
||||||
|
// Calculate offsets
|
||||||
|
if (top < 0) { topOffset = -top; }
|
||||||
|
if (left < 0) { leftOffset = -left; }
|
||||||
|
if (right < 0) { leftOffset = right; }
|
||||||
|
if (bottom < 0) { topOffset = bottom; }
|
||||||
|
if (height < minHeight) { heightOffset = minHeight - height; }
|
||||||
|
if (height > maxHeight) { heightOffset = maxHeight - height; }
|
||||||
|
|
||||||
|
// Establish limits
|
||||||
|
left = Math.max(left + leftOffset, 0);
|
||||||
|
top = Math.max(top + topOffset, 0);
|
||||||
|
height = Math.max(height + heightOffset, minHeight);
|
||||||
|
|
||||||
|
// Set the new position/size
|
||||||
|
this.$terminal.animate({
|
||||||
|
left: left + 'px',
|
||||||
|
top: top + 'px',
|
||||||
|
height: height + 'px'
|
||||||
|
}, this.getAnimationTime(), function () {
|
||||||
|
parent.trigger('resizeCanvas');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getCanvasLocation: function() {
|
getCanvasLocation: function() {
|
||||||
|
|
|
@ -89,6 +89,7 @@ var LevelDropdownView = ContainedBase.extend({
|
||||||
if (id === this.JSON.selectedTab) {
|
if (id === this.JSON.selectedTab) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.selectedTab = id;
|
||||||
this.updateTabTo(id);
|
this.updateTabTo(id);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var Q = require('q');
|
var Q = require('q');
|
||||||
var Backbone = require('backbone');
|
var Backbone = require('backbone');
|
||||||
var GLOBAL = require('../../util/constants').GLOBAL;
|
var GlobalState = require('../../util/globalState');
|
||||||
var GRAPHICS = require('../../util/constants').GRAPHICS;
|
var GRAPHICS = require('../../util/constants').GRAPHICS;
|
||||||
|
|
||||||
var Animation = Backbone.Model.extend({
|
var Animation = Backbone.Model.extend({
|
||||||
|
@ -67,13 +67,13 @@ var AnimationQueue = Backbone.Model.extend({
|
||||||
this.set('index', 0);
|
this.set('index', 0);
|
||||||
|
|
||||||
// set the global lock that we are animating
|
// set the global lock that we are animating
|
||||||
GLOBAL.isAnimating = true;
|
GlobalState.isAnimating = true;
|
||||||
this.next();
|
this.next();
|
||||||
},
|
},
|
||||||
|
|
||||||
finish: function() {
|
finish: function() {
|
||||||
// release lock here
|
// release lock here
|
||||||
GLOBAL.isAnimating = false;
|
GlobalState.isAnimating = false;
|
||||||
this.get('callback')();
|
this.get('callback')();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ var Q = require('q');
|
||||||
var Backbone = require('backbone');
|
var Backbone = require('backbone');
|
||||||
|
|
||||||
var GRAPHICS = require('../util/constants').GRAPHICS;
|
var GRAPHICS = require('../util/constants').GRAPHICS;
|
||||||
var GLOBAL = require('../util/constants').GLOBAL;
|
var GlobalState = require('../util/globalState');
|
||||||
|
|
||||||
var Collections = require('../models/collections');
|
var Collections = require('../models/collections');
|
||||||
var CommitCollection = Collections.CommitCollection;
|
var CommitCollection = Collections.CommitCollection;
|
||||||
|
@ -124,10 +124,13 @@ GitVisuals.prototype.initHeadBranch = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
GitVisuals.prototype.getScreenPadding = function() {
|
GitVisuals.prototype.getScreenPadding = function() {
|
||||||
|
// if we are flipping the tree, the helper bar gets in the way
|
||||||
|
var topFactor = (GlobalState.flipTreeY) ? 3 : 1.5;
|
||||||
|
|
||||||
// for now we return the node radius subtracted from the walls
|
// for now we return the node radius subtracted from the walls
|
||||||
return {
|
return {
|
||||||
widthPadding: GRAPHICS.nodeRadius * 1.5,
|
widthPadding: GRAPHICS.nodeRadius * 1.5,
|
||||||
topHeightPadding: GRAPHICS.nodeRadius * 1.5,
|
topHeightPadding: GRAPHICS.nodeRadius * topFactor,
|
||||||
// we pad the bottom a lot more so the branches wont go off screen
|
// we pad the bottom a lot more so the branches wont go off screen
|
||||||
bottomHeightPadding: GRAPHICS.nodeRadius * 5
|
bottomHeightPadding: GRAPHICS.nodeRadius * 5
|
||||||
};
|
};
|
||||||
|
@ -180,10 +183,15 @@ GitVisuals.prototype.toScreenCoords = function(pos) {
|
||||||
return paddingTop + frac * (total - paddingBelow - paddingTop);
|
return paddingTop + frac * (total - paddingBelow - paddingTop);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
var x = shrink(pos.x, this.paper.width, padding.widthPadding);
|
||||||
x: shrink(pos.x, this.paper.width, padding.widthPadding),
|
var y =
|
||||||
y: asymShrink(pos.y, this.paper.height, padding.topHeightPadding, padding.bottomHeightPadding)
|
asymShrink(pos.y, this.paper.height, padding.topHeightPadding, padding.bottomHeightPadding);
|
||||||
};
|
|
||||||
|
if (GlobalState.flipTreeY) {
|
||||||
|
y = this.paper.height - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {x: x, y: y};
|
||||||
};
|
};
|
||||||
|
|
||||||
GitVisuals.prototype.animateAllAttrKeys = function(keys, attr, speed, easing) {
|
GitVisuals.prototype.animateAllAttrKeys = function(keys, attr, speed, easing) {
|
||||||
|
@ -782,14 +790,7 @@ GitVisuals.prototype.canvasResize = function(width, height) {
|
||||||
GitVisuals.prototype.genResizeFunc = function() {
|
GitVisuals.prototype.genResizeFunc = function() {
|
||||||
this.resizeFunc = _.debounce(
|
this.resizeFunc = _.debounce(
|
||||||
_.bind(function(width, height) {
|
_.bind(function(width, height) {
|
||||||
|
|
||||||
// refresh when we are ready if we are animating som ething
|
|
||||||
if (false && GLOBAL.isAnimating) {
|
|
||||||
var Main = require('../app');
|
|
||||||
Main.getEventBaton().trigger('commandSubmitted', 'refresh');
|
|
||||||
} else {
|
|
||||||
this.refreshTree();
|
this.refreshTree();
|
||||||
}
|
|
||||||
}, this),
|
}, this),
|
||||||
200,
|
200,
|
||||||
true
|
true
|
||||||
|
|
|
@ -3,6 +3,7 @@ var Backbone = require('backbone');
|
||||||
var GRAPHICS = require('../util/constants').GRAPHICS;
|
var GRAPHICS = require('../util/constants').GRAPHICS;
|
||||||
|
|
||||||
var VisBase = require('../visuals/visBase').VisBase;
|
var VisBase = require('../visuals/visBase').VisBase;
|
||||||
|
var GlobalState = require('../util/globalState');
|
||||||
|
|
||||||
var VisEdge = VisBase.extend({
|
var VisEdge = VisBase.extend({
|
||||||
defaults: {
|
defaults: {
|
||||||
|
@ -51,6 +52,7 @@ var VisEdge = VisBase.extend({
|
||||||
// is M(move abs) C (curve to) (control point 1) (control point 2) (final point)
|
// is M(move abs) C (curve to) (control point 1) (control point 2) (final point)
|
||||||
// the control points have to be __below__ to get the curve starting off straight.
|
// the control points have to be __below__ to get the curve starting off straight.
|
||||||
|
|
||||||
|
var flipFactor = (GlobalState.flipTreeY) ? -1 : 1;
|
||||||
var coords = function(pos) {
|
var coords = function(pos) {
|
||||||
return String(Math.round(pos.x)) + ',' + String(Math.round(pos.y));
|
return String(Math.round(pos.x)) + ',' + String(Math.round(pos.y));
|
||||||
};
|
};
|
||||||
|
@ -58,19 +60,19 @@ var VisEdge = VisBase.extend({
|
||||||
delta = delta || GRAPHICS.curveControlPointOffset;
|
delta = delta || GRAPHICS.curveControlPointOffset;
|
||||||
return {
|
return {
|
||||||
x: pos.x,
|
x: pos.x,
|
||||||
y: pos.y + delta * dir
|
y: pos.y + flipFactor * delta * dir
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
var offset2d = function(pos, x, y) {
|
var offset2d = function(pos, x, y) {
|
||||||
return {
|
return {
|
||||||
x: pos.x + x,
|
x: pos.x + x,
|
||||||
y: pos.y + y
|
y: pos.y + flipFactor * y
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// first offset tail and head by radii
|
// first offset tail and head by radii
|
||||||
tailPos = offset(tailPos, -1, this.get('tail').getRadius());
|
tailPos = offset(tailPos, -1, this.get('tail').getRadius());
|
||||||
headPos = offset(headPos, 1, this.get('head').getRadius());
|
headPos = offset(headPos, 1, this.get('head').getRadius() * 1.15);
|
||||||
|
|
||||||
var str = '';
|
var str = '';
|
||||||
// first move to bottom of tail
|
// first move to bottom of tail
|
||||||
|
|
|
@ -74,6 +74,13 @@ var Visualization = Backbone.View.extend({
|
||||||
this.myResize();
|
this.myResize();
|
||||||
}, this));
|
}, this));
|
||||||
|
|
||||||
|
// If the visualization is within a draggable container, we need to update the
|
||||||
|
// position whenever the container is moved.
|
||||||
|
this.$el.parents('.ui-draggable').on('drag', _.bind(function(event, ui) {
|
||||||
|
this.customEvents.trigger('drag', event, ui);
|
||||||
|
this.myResize();
|
||||||
|
}, this));
|
||||||
|
|
||||||
this.gitVisuals.drawTreeFirstTime();
|
this.gitVisuals.drawTreeFirstTime();
|
||||||
if (this.treeString) {
|
if (this.treeString) {
|
||||||
this.gitEngine.loadTreeFromString(this.treeString);
|
this.gitEngine.loadTreeFromString(this.treeString);
|
||||||
|
@ -182,12 +189,14 @@ var Visualization = Backbone.View.extend({
|
||||||
$(this.paper.canvas).css('visibility', 'visible');
|
$(this.paper.canvas).css('visibility', 'visible');
|
||||||
setTimeout(_.bind(this.fadeTreeIn, this), 10);
|
setTimeout(_.bind(this.fadeTreeIn, this), 10);
|
||||||
this.originToo('show', arguments);
|
this.originToo('show', arguments);
|
||||||
|
this.myResize();
|
||||||
},
|
},
|
||||||
|
|
||||||
showHarsh: function() {
|
showHarsh: function() {
|
||||||
$(this.paper.canvas).css('visibility', 'visible');
|
$(this.paper.canvas).css('visibility', 'visible');
|
||||||
this.setTreeOpacity(1);
|
this.setTreeOpacity(1);
|
||||||
this.originToo('showHarsh', arguments);
|
this.originToo('showHarsh', arguments);
|
||||||
|
this.myResize();
|
||||||
},
|
},
|
||||||
|
|
||||||
resetFromThisTreeNow: function(treeString) {
|
resetFromThisTreeNow: function(treeString) {
|
||||||
|
@ -257,8 +266,8 @@ var Visualization = Backbone.View.extend({
|
||||||
// if we don't have a container, we need to set our
|
// if we don't have a container, we need to set our
|
||||||
// position absolutely to whatever we are tracking
|
// position absolutely to whatever we are tracking
|
||||||
if (!this.containerElement) {
|
if (!this.containerElement) {
|
||||||
var left = el.offsetLeft;
|
var left = this.$el.offset().left;
|
||||||
var top = el.offsetTop;
|
var top = this.$el.offset().top;
|
||||||
|
|
||||||
$(this.paper.canvas).css({
|
$(this.paper.canvas).css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -274,6 +283,7 @@ var Visualization = Backbone.View.extend({
|
||||||
|
|
||||||
this.paper.setSize(width, height);
|
this.paper.setSize(width, height);
|
||||||
this.gitVisuals.canvasResize(width, height);
|
this.gitVisuals.canvasResize(width, height);
|
||||||
|
this.originToo('myResize', arguments);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ exports.level = {
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Multiple parents",
|
"en_US": "Multiple parents",
|
||||||
"zh_CN": "多个父提交记录",
|
"zh_CN": "多个父提交记录",
|
||||||
|
"de_DE": "Mehrere Vorgänger",
|
||||||
"zh_TW": "多個 parent commit"
|
"zh_TW": "多個 parent commit"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Use `git branch bugWork` with a target commit to create the missing reference.",
|
"en_US": "Use `git branch bugWork` with a target commit to create the missing reference.",
|
||||||
"zh_CN": "使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。",
|
"de_DE": "Nutze `git branch bugWork` mit einem Ziel-Commit um die fehlende Referenz zu erstellen.",
|
||||||
|
"zh_CN": "使用`git branch bugWork`加上一个目标提交记录来创建消失的引用。"
|
||||||
"zh_TW": "在一個指定的 commit 上面使用 `git branch bugWork`。"
|
"zh_TW": "在一個指定的 commit 上面使用 `git branch bugWork`。"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
|
@ -100,6 +102,93 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Vorgänger ansteuern",
|
||||||
|
"",
|
||||||
|
"Wie der Operator `~` akzeptiert auch der Operator `^` eine optionale Anzahl.",
|
||||||
|
"",
|
||||||
|
"Anstatt der Anzahl von Schritten, die zurückgegangen werden soll (das ist das, was man bei `~` angibt), bezeichnet die Anzahl nach `^` welchem Vorgänger bei einem Merge-Commit gefolgt werden soll. Du erinnerst dich, dass ein Merge-Commit mehrere Vorgänger hat; es gilt also aus diesen auszuwählen.",
|
||||||
|
"",
|
||||||
|
"Normalerweise folgt Git dem \"ersten\" Vorgänger des Merge-Commit, aber durch Angabe einer Zahl nach dem `^` lässt sich dieses Verhalten ändern.",
|
||||||
|
"",
|
||||||
|
"Aber genug gequatscht, schauen wir's uns in Aktion an.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Hier sehen wir einen Merge-Commit. Wenn wir einen Checkout von `master^` ohne Zahl machen, wird Git auf den ersten Vorgänger des Commits zurückgehen. ",
|
||||||
|
"",
|
||||||
|
"*(In unserer Darstellung befindet sich der erste Vorgänger direkt über dem Merge-Commit.)*"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Simpel -- so kennen wir das."
|
||||||
|
],
|
||||||
|
"command": "git checkout master^",
|
||||||
|
"beforeCommand": "git checkout HEAD^; git commit; git checkout master; git merge C2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Jetzt versuchen wir mal stattdessen den zweiten Vorgänger anzugeben ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Gesehen? Wir gehen zu dem anderen Vorgänger zurück."
|
||||||
|
],
|
||||||
|
"command": "git checkout master^2",
|
||||||
|
"beforeCommand": "git checkout HEAD^; git commit; git checkout master; git merge C2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Die Operatoren `^` und `~` geben uns eine Menge Möglichkeiten für das Navigieren durch den Commit-Baum:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Bämm!"
|
||||||
|
],
|
||||||
|
"command": "git checkout HEAD~; git checkout HEAD^2; git checkout HEAD~2",
|
||||||
|
"beforeCommand": "git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Noch abgefahrener: die beiden Operatoren können verkettet werden. Aufgepasst:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Gleicher Ablauf wie zuvor, nur alles in einem Befehl."
|
||||||
|
],
|
||||||
|
"command": "git checkout HEAD~^2~2",
|
||||||
|
"beforeCommand": "git commit; git checkout C0; git commit; git commit; git commit; git checkout master; git merge C5; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Setzen wir's um",
|
||||||
|
"",
|
||||||
|
"Erstelle einen neuen Branch an dem angegebenen Ziel, um diesen Level abzuschließen.",
|
||||||
|
"",
|
||||||
|
"Es ist natürlich möglich den Commit einfach direkt anzugeben (also mit sowas wie `C6`), aber ich fordere dich heraus stattdessen die relativen Operatoren zu benutzen!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"zh_CN": {
|
"zh_CN": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,6 +55,7 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
intro: {
|
intro: {
|
||||||
displayName: {
|
displayName: {
|
||||||
'en_US': 'Introduction Sequence',
|
'en_US': 'Introduction Sequence',
|
||||||
|
'de_DE': 'Einführung',
|
||||||
'ja': 'まずはここから',
|
'ja': 'まずはここから',
|
||||||
'fr_FR': 'Séquence d\'introduction',
|
'fr_FR': 'Séquence d\'introduction',
|
||||||
'zh_CN': '基础篇',
|
'zh_CN': '基础篇',
|
||||||
|
@ -63,6 +64,7 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
'en_US': 'A nicely paced introduction to the majority of git commands',
|
'en_US': 'A nicely paced introduction to the majority of git commands',
|
||||||
|
'de_DE': 'Eine gut abgestimmte Einführung in die wichtigsten Git-Befehle',
|
||||||
'ja': 'gitの基本的なコマンド群をほどよいペースで学ぶ',
|
'ja': 'gitの基本的なコマンド群をほどよいペースで学ぶ',
|
||||||
'fr_FR': 'Une introduction en douceur à la majorité des commandes git',
|
'fr_FR': 'Une introduction en douceur à la majorité des commandes git',
|
||||||
'zh_CN': '循序渐进介绍git主要命令',
|
'zh_CN': '循序渐进介绍git主要命令',
|
||||||
|
@ -73,6 +75,7 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
rampup: {
|
rampup: {
|
||||||
displayName: {
|
displayName: {
|
||||||
'en_US': 'Ramping Up',
|
'en_US': 'Ramping Up',
|
||||||
|
'de_DE': 'Aufstieg',
|
||||||
'ja': '次のレベルに進もう',
|
'ja': '次のレベルに進もう',
|
||||||
'fr_FR': 'Montée en puissance',
|
'fr_FR': 'Montée en puissance',
|
||||||
'zh_CN': '进阶篇',
|
'zh_CN': '进阶篇',
|
||||||
|
@ -80,6 +83,7 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
'en_US': 'The next serving of 100% git awesomes-ness. Hope you\'re hungry',
|
'en_US': 'The next serving of 100% git awesomes-ness. Hope you\'re hungry',
|
||||||
|
'de_DE': 'Eine Portion Git-Wahnsinn zum Thema Navigation',
|
||||||
'ja': '更にgitの素晴らしさを堪能しよう',
|
'ja': '更にgitの素晴らしさを堪能しよう',
|
||||||
'fr_FR' : 'Le prochain service git 100% excellence. J\'espère que vous êtes affamés',
|
'fr_FR' : 'Le prochain service git 100% excellence. J\'espère que vous êtes affamés',
|
||||||
'zh_CN': '接下来是git的超赞特性。迫不及待了吧!',
|
'zh_CN': '接下来是git的超赞特性。迫不及待了吧!',
|
||||||
|
@ -89,24 +93,33 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
remote: {
|
remote: {
|
||||||
tab: 'remote',
|
tab: 'remote',
|
||||||
displayName: {
|
displayName: {
|
||||||
'en_US': 'Push & Pull -- Git Remotes!'
|
'en_US': 'Push & Pull -- Git Remotes!',
|
||||||
|
'de_DE': 'Push & Pull -- entfernte Repositorys',
|
||||||
|
'zh_CN': 'Push & Pull -- Git Remotes!'
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
'en_US': 'Time to share your 1\'s and 0\'s kids; coding just got social'
|
'en_US': 'Time to share your 1\'s and 0\'s kids; coding just got social',
|
||||||
|
'de_DE': 'Zeit Eure 1en und 0en zu teilen; Coding mit sozialer Komponente',
|
||||||
|
'zh_CN': '是时候分享你的编码了'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
remoteAdvanced: {
|
remoteAdvanced: {
|
||||||
tab: 'remote',
|
tab: 'remote',
|
||||||
displayName: {
|
displayName: {
|
||||||
'en_US': 'To Origin And Beyond -- Advanced Git Remotes!'
|
'en_US': 'To Origin And Beyond -- Advanced Git Remotes!',
|
||||||
|
'de_DE': 'Bis zum origin und noch weiter',
|
||||||
|
'zh_CN': '关于origin 和 其它仓库 -- Git Gemotes 高级命令'
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
'en_US': 'And you thought being a benevolent dictator would be fun...'
|
'en_US': 'And you thought being a benevolent dictator would be fun...',
|
||||||
|
'zh_CN': '做一名仁慈的独裁者会很有趣..',
|
||||||
|
'de_DE': 'Git Remotes für Fortgeschrittene'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
move: {
|
move: {
|
||||||
displayName: {
|
displayName: {
|
||||||
'en_US': 'Moving Work Around',
|
'en_US': 'Moving Work Around',
|
||||||
|
'de_DE': 'Code Umherschieben',
|
||||||
// INTL out of sync :(
|
// INTL out of sync :(
|
||||||
'ja': 'Rebaseをモノにする',
|
'ja': 'Rebaseをモノにする',
|
||||||
'fr_FR': 'Maîtrise Rebase, Luke!',
|
'fr_FR': 'Maîtrise Rebase, Luke!',
|
||||||
|
@ -116,6 +129,7 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
'en_US': 'Get comfortable with modifying the source tree',
|
'en_US': 'Get comfortable with modifying the source tree',
|
||||||
|
'de_DE': 'Gewöhn dich daran, den Git-Baum zu verändern',
|
||||||
// INTL out of sync :(
|
// INTL out of sync :(
|
||||||
'ja': '話題のrebaseってどんなものだろう?って人にオススメ',
|
'ja': '話題のrebaseってどんなものだろう?って人にオススメ',
|
||||||
'fr_FR': 'Qu\'est-ce que ce rebase dont tout le monde parle ? Découvrez-le !',
|
'fr_FR': 'Qu\'est-ce que ce rebase dont tout le monde parle ? Découvrez-le !',
|
||||||
|
@ -127,6 +141,7 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
mixed: {
|
mixed: {
|
||||||
displayName: {
|
displayName: {
|
||||||
'en_US': 'A Mixed Bag',
|
'en_US': 'A Mixed Bag',
|
||||||
|
'de_DE': 'Ein Kessel Buntes',
|
||||||
'ja': '様々なtips',
|
'ja': '様々なtips',
|
||||||
'fr_FR': 'Un assortiment',
|
'fr_FR': 'Un assortiment',
|
||||||
'ko': '종합선물세트',
|
'ko': '종합선물세트',
|
||||||
|
@ -135,6 +150,7 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
'en_US': 'A mixed bag of Git techniques, tricks, and tips',
|
'en_US': 'A mixed bag of Git techniques, tricks, and tips',
|
||||||
|
'de_DE': 'Eine bunte Mischung von Techniken, Tipps und Tricks',
|
||||||
'ja': 'gitを使う上での様々なtipsやテクニックなど',
|
'ja': 'gitを使う上での様々なtipsやテクニックなど',
|
||||||
'fr_FR': 'Un assortiment de techniques et astuces pour utiliser Git',
|
'fr_FR': 'Un assortiment de techniques et astuces pour utiliser Git',
|
||||||
'ko': 'Git을 다루는 다양한 팁과 테크닉을 다양하게 알아봅니다',
|
'ko': 'Git을 다루는 다양한 팁과 테크닉을 다양하게 알아봅니다',
|
||||||
|
@ -145,12 +161,14 @@ var sequenceInfo = exports.sequenceInfo = {
|
||||||
advanced: {
|
advanced: {
|
||||||
displayName: {
|
displayName: {
|
||||||
'en_US': 'Advanced Topics',
|
'en_US': 'Advanced Topics',
|
||||||
|
'de_DE': 'Themen für Fortgeschrittene',
|
||||||
'fr_FR': 'Sujets Avancés',
|
'fr_FR': 'Sujets Avancés',
|
||||||
'zh_CN': '高级主题',
|
'zh_CN': '高级主题',
|
||||||
'zh_TW': '進階主題'
|
'zh_TW': '進階主題'
|
||||||
},
|
},
|
||||||
about: {
|
about: {
|
||||||
'en_US': 'For the truly brave!',
|
'en_US': 'For the truly brave!',
|
||||||
|
'de_DE': '... die nie ein Mensch zuvor gesehen hat.',
|
||||||
'fr_FR': 'Pour les plus courageux !',
|
'fr_FR': 'Pour les plus courageux !',
|
||||||
'zh_CN': '只为真正的勇士!',
|
'zh_CN': '只为真正的勇士!',
|
||||||
'zh_TW': '來成為真正的強者吧!'
|
'zh_TW': '來成為真正的強者吧!'
|
||||||
|
|
|
@ -3,6 +3,7 @@ exports.level = {
|
||||||
"solutionCommand": "git branch bugFix;git checkout bugFix",
|
"solutionCommand": "git branch bugFix;git checkout bugFix",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Branching in Git",
|
"en_US": "Branching in Git",
|
||||||
|
"de_DE": "Branches in Git",
|
||||||
"ja": "Gitのブランチ",
|
"ja": "Gitのブランチ",
|
||||||
"ko": "Git에서 브랜치 쓰기",
|
"ko": "Git에서 브랜치 쓰기",
|
||||||
"fr_FR": "Gérer les branches avec Git",
|
"fr_FR": "Gérer les branches avec Git",
|
||||||
|
@ -11,6 +12,7 @@ exports.level = {
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Make a new branch with \"git branch [name]\" and check it out with \"git checkout [name]\"",
|
"en_US": "Make a new branch with \"git branch [name]\" and check it out with \"git checkout [name]\"",
|
||||||
|
"de_DE": 'Lege mit "git branch <Name>" einen neuen Branch an und checke ihn mit "git checkout <Name> aus',
|
||||||
"ja": "ブランチの作成(\"git branch [ブランチ名]\")と、チェックアウト(\"git checkout [ブランチ名]\")",
|
"ja": "ブランチの作成(\"git branch [ブランチ名]\")と、チェックアウト(\"git checkout [ブランチ名]\")",
|
||||||
"fr_FR": "Faites une nouvelle branche avec \"git branch [nom]\" positionnez-vous dans celle-ci avec \"git checkout [nom]\"",
|
"fr_FR": "Faites une nouvelle branche avec \"git branch [nom]\" positionnez-vous dans celle-ci avec \"git checkout [nom]\"",
|
||||||
"zh_CN": "用 'git branch [分支名]' 来创建分支,用 'git checkout [分支名]' 切换到分支",
|
"zh_CN": "用 'git branch [分支名]' 来创建分支,用 'git checkout [分支名]' 切换到分支",
|
||||||
|
@ -99,6 +101,79 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Branches in Git",
|
||||||
|
"",
|
||||||
|
"Branches sind in Git extrem schlank. Sie sind einfach Verweise auf einen bestimmten Commit -- das ist alles. Es ist unter Git-Enthusiasten deshalb gängige Praxis, früh und oft Branches anzulegen.",
|
||||||
|
"",
|
||||||
|
"Da das Anlegen von Branches keinen Plattenplatz und Speicher verbraucht, liegt es nahe die Arbeit in kleine logische Häppchen aufzuteilen, anstatt mit wenigen großen, monolithischen Branches zu hantieren.",
|
||||||
|
"",
|
||||||
|
"Wir werden sehen wie Commits und Branches zusammengehören sobald wir anfangen mit beiden zu arbeiten. Bis hierhin merk dir einfach, dass ein Branch im Prinzip bedeutet \"ich möchte die Arbeit, die in diesem Commit und seinen Vorgändern steckt, sichern\"."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir mal, wie Branches in der Praxis aussehen.",
|
||||||
|
"",
|
||||||
|
"Wir legen einen neuen Branch an und nennen ihn `issue`:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Und das war's auch schon, mehr ist es nicht. Der Branch `issue` zeigt nun auf den Commit `C1`."
|
||||||
|
],
|
||||||
|
"command": "git branch issue",
|
||||||
|
"beforeCommand": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Lass uns mal ein wenig auf dem neuen Branch arbeiten. Machen wir einen Commit:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Oi! Der Branch `master` hat sich verändert, aber der Branch `issue` nicht. Das liegt daran, dass wir nicht \"auf\" dem neuen Branch waren, weshalb das Sternchen `*` auch hinter `master` steht."
|
||||||
|
],
|
||||||
|
"command": "git commit",
|
||||||
|
"beforeCommand": "git branch issue"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Sagen wir Git also erst mal auf welchem Branch wir arbeiten wollen, und zwar mit",
|
||||||
|
"",
|
||||||
|
"```",
|
||||||
|
"git checkout <Name>",
|
||||||
|
"```",
|
||||||
|
"",
|
||||||
|
"Das wird uns auf den neuen Branch bringen bevor wir unsere Änderungen committen."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Und fertig! Unsere Änderungen wurden im neuen Branch gespeichert."
|
||||||
|
],
|
||||||
|
"command": "git checkout issue; git commit",
|
||||||
|
"beforeCommand": "git branch issue"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Cool! Jetzt bist du soweit, selbst Branches anzulegen. Wenn dieses Fenster geschlossen wurde, leg einen neuen Branch namens `bugFix` an und schalte auf diesen um."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
exports.level = {
|
exports.level = {
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Introduction to Git Commits",
|
"en_US": "Introduction to Git Commits",
|
||||||
|
"de_DE": "Einführung in Git Commits",
|
||||||
"fr_FR": "Introduction aux commits avec Git",
|
"fr_FR": "Introduction aux commits avec Git",
|
||||||
"ja": "Gitのコミット",
|
"ja": "Gitのコミット",
|
||||||
'ko': 'Git 커밋 소개',
|
'ko': 'Git 커밋 소개',
|
||||||
|
@ -12,6 +13,7 @@ exports.level = {
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Just type in 'git commit' twice to finish!",
|
"en_US": "Just type in 'git commit' twice to finish!",
|
||||||
|
"de_DE": "Gib einfach zweimal 'git commit' ein um den Level abzuschließen",
|
||||||
"fr_FR": "Il suffit de saisir 'git commit' deux fois pour réussir !",
|
"fr_FR": "Il suffit de saisir 'git commit' deux fois pour réussir !",
|
||||||
"zh_CN": "敲两次 'git commit' 就好啦!",
|
"zh_CN": "敲两次 'git commit' 就好啦!",
|
||||||
"zh_TW": "輸入兩次 'git commit' 就可以完成!",
|
"zh_TW": "輸入兩次 'git commit' 就可以完成!",
|
||||||
|
@ -64,6 +66,48 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Commits",
|
||||||
|
"Ein Commit in ein Git-Repository speichert einen Abbildung aller Dateien in deinem Projektverzeichnis. Es ist wie ein riesiges Kopieren und Einfügen, nur besser.",
|
||||||
|
"",
|
||||||
|
"Allerdings will Git die Commits so schlank wie möglich halten, also kopiert es nicht einfach stur das ganze Verzeichnis jedes Mal wenn du committest. Es kann (wenn möglich) Commits als Menge von Änderungen zusammenpacken, von einer Version des Repositorys zur nächsten.",
|
||||||
|
"",
|
||||||
|
"Außerdem führt Git ein Protokoll darüber welche Commits wann gemacht wurden, und welcher auf welchen folgt. Deshalb werden die Commits hier mit ihrem Vorgänger über sich gezeigt -- wir verwenden Pfeile zur Darstellung der Beziehung. Dieses Protokoll zu haben ist eine tolle Sache für jeden, der an einem Projekt arbeitet.",
|
||||||
|
"",
|
||||||
|
"Das war jetzt eine Menge Neues, aber vorerst kannst du dir Commits einfach als Abbildungen des Projekts vorstellen. Commits sind sehr ressourcenschonend, und zwischen ihnen wechseln geht superschnell!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Mal sehen wie das in der Praxis ist. Rechts sehen wir ein (kleines) Git-Repository. Es gibt akutell zwei Commits -- den initialen, `C0`, und den danach, `C1`, der irgendwelche Änderungen enthält.",
|
||||||
|
"",
|
||||||
|
"Klick die Schaltfläche unten um einen neuen Commit zu erzeugen:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Fertig. Klasse! Wir haben gerade Änderungen gemacht und als Commit im Repository gespeichert. Der Commit, den wir gerade gemacht haben, hat den Vorgänger `C1`; der verweist wiederum auf den Commit, auf dem er basiert: `C0`."
|
||||||
|
],
|
||||||
|
"command": "git commit",
|
||||||
|
"beforeCommand": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Probier das committen gleich mal aus! Mach zwei Commits um den Level abzuschließen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ exports.level = {
|
||||||
"solutionCommand": "git checkout -b bugFix;git commit;git checkout master;git commit;git merge bugFix",
|
"solutionCommand": "git checkout -b bugFix;git commit;git checkout master;git commit;git merge bugFix",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Merging in Git",
|
"en_US": "Merging in Git",
|
||||||
|
"de_DE": "Mergen in git",
|
||||||
"fr_FR": "Faire des 'merge' (fusions de branches) avec Git",
|
"fr_FR": "Faire des 'merge' (fusions de branches) avec Git",
|
||||||
"ko": "Git에서 브랜치 합치기(Merge)",
|
"ko": "Git에서 브랜치 합치기(Merge)",
|
||||||
"ja": "ブランチとマージ",
|
"ja": "ブランチとマージ",
|
||||||
|
@ -11,6 +12,7 @@ exports.level = {
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember to commit in the order specified (bugFix before master)",
|
"en_US": "Remember to commit in the order specified (bugFix before master)",
|
||||||
|
"de_DE": "Denk dran in der angegebenen Reihenfolge zu committen (erst bugFix, dann master)",
|
||||||
"ja": "指示された順番でコミットすること(masterの前にbugFixで)",
|
"ja": "指示された順番でコミットすること(masterの前にbugFixで)",
|
||||||
"fr_FR": "Pensez à faire des commits dans l'ordre indiqué (bugFix avant master)",
|
"fr_FR": "Pensez à faire des commits dans l'ordre indiqué (bugFix avant master)",
|
||||||
"zh_CN": "记住按指定的顺序提交(bugFix先于master)",
|
"zh_CN": "记住按指定的顺序提交(bugFix先于master)",
|
||||||
|
@ -90,6 +92,75 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Branches und Mergen",
|
||||||
|
"",
|
||||||
|
"Super! Wir wissen jetzt, wie man committet und einen Branch anlegt. Jetzt müssen wir nur noch rauskriegen, wie man die Arbeit, die in verschiedenen Branches steckt, zusammenführen kann. Dann können wir einen neuen Branch erstellen, darin ein neues Feature entwickeln, und das dann in den ursprünglichen Zweig integrieren.",
|
||||||
|
"",
|
||||||
|
"Die einfachste Methode, mit der man Branches zusammenführen kann, ist `git merge`. Das Mergen erzeugt in git einen speziellen Commit, der zwei Vorgänger hat. Ein solcher Commit bedeutet im Prinzip \"ich möchte alle Arbeit von dem Vorgänger hier und dem dort *und* allen ihren jeweiligen Vorgängern miteinander kombinieren\".",
|
||||||
|
"",
|
||||||
|
"Grafisch dargestellt ist es einfacher zu verstehen, lass es uns mal ansehen"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Hier haben wir zwei Branches; jeder besteht jeweils aus einem eigenen Commit. Das bedeutet, dass keiner der beiden Branches alle Inhalte des gesamten Repositorys kennt. Das werden wir mit einem Merge ändern.",
|
||||||
|
"",
|
||||||
|
"Wir werden den Branch `bugFix` in `master` integrieren"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Wow! Hast du das gesehen? Zunächst mal zeigt `master` jetzt auf einen Commit mit zwei Vorgängern. Wenn du den beiden Pfeilen immer weiter folgst, kommst du an jedem Commit im Repository vorbei. Das heißt `master` enthält jetzt alles, was es im Repository gibt.",
|
||||||
|
"",
|
||||||
|
"Siehst du außerdem wie sich die Farben der Commits verändert haben? Um die Vorgänge zu verdeutlichen hab ich etwas Farbe ins Spiel gebracht. Jeder Branch hat seine eindeutige Farbe. Jeder Merge Commit bekommt als Farbe eine Mischung aus den Farben seiner Vorgänger.",
|
||||||
|
"",
|
||||||
|
"Wir sehen also, dass die Farbe des Branch `master` in alle Commits gemischt wurde, die von `bugFix` aber nicht. Ändern wir das ..."
|
||||||
|
],
|
||||||
|
"command": "git merge bugFix",
|
||||||
|
"beforeCommand": "git checkout -b bugFix; git commit; git checkout master; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Mergen wir `master` in `bugFix`:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Da `bugFix` ein Vorgänger von `master` war, musste git hier kaum etwas tun; es verschiebt `bugFix` einfach auf den Commit, auf den auch `master` zeigt.",
|
||||||
|
"",
|
||||||
|
"Jetzt haben alle Commits dieselbe Farbe, das heißt jeder Branch enthält die Informationen des gesamten Repositorys! Juhu!"
|
||||||
|
],
|
||||||
|
"command": "git checkout bugFix; git merge master",
|
||||||
|
"beforeCommand": "git checkout -b bugFix; git commit; git checkout master; git commit; git merge bugFix"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Führe folgendes aus, um diesen Level zu schaffen:",
|
||||||
|
"",
|
||||||
|
"* Lege einen neuen Branch `bugFix` an",
|
||||||
|
"* Checke `bugFix` aus mittels `git checkout bugFix`",
|
||||||
|
"* Mach einen Commit",
|
||||||
|
"* Geh mit `git checkout` zum `master` zurück",
|
||||||
|
"* Mach noch einen Commit",
|
||||||
|
"* Merge den Branch `bugFix` in `master` mit `git merge`",
|
||||||
|
"",
|
||||||
|
"*Denk dran, du kannst diese Meldung mit dem Befehl `help level` so oft anzeigen, wie du willst!*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ exports.level = {
|
||||||
"solutionCommand": "git checkout -b bugFix;git commit;git checkout master;git commit;git checkout bugFix;git rebase master",
|
"solutionCommand": "git checkout -b bugFix;git commit;git checkout master;git commit;git checkout bugFix;git rebase master",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Rebase Introduction",
|
"en_US": "Rebase Introduction",
|
||||||
|
"de_DE": "Einführung in Rebase",
|
||||||
"ja": "Rebaseの解説",
|
"ja": "Rebaseの解説",
|
||||||
"fr_FR": "Introduction à rebase",
|
"fr_FR": "Introduction à rebase",
|
||||||
"ko": "리베이스(rebase)의 기본",
|
"ko": "리베이스(rebase)의 기본",
|
||||||
|
@ -11,6 +12,7 @@ exports.level = {
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Make sure you commit from bugFix first",
|
"en_US": "Make sure you commit from bugFix first",
|
||||||
|
"de_DE": "Geh vor dem committen sicher, dass du auf bugFix arbeitest",
|
||||||
"ja": "初めにbugFixを指した状態でコミットする",
|
"ja": "初めにbugFixを指した状態でコミットする",
|
||||||
"fr_FR": "Assurez-vous de bien faire votre en premier votre commit sur bugFix",
|
"fr_FR": "Assurez-vous de bien faire votre en premier votre commit sur bugFix",
|
||||||
"ko": "bugFix 브랜치에서 먼저 커밋하세요",
|
"ko": "bugFix 브랜치에서 먼저 커밋하세요",
|
||||||
|
@ -88,6 +90,73 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Rebase",
|
||||||
|
"",
|
||||||
|
"Der zweite Weg um Inhalte aus verschiedenen Branches zu kombinieren ist `git rebase`. Rebasen nimmt im Prinzip eine Menge von Commits, \"kopiert\" sie und packt sie auf etwas anderes drauf.",
|
||||||
|
"",
|
||||||
|
"Auch wenn das erst mal komisch klingt liegt der Vorteil von Rebase darin, dass man es benutzen kann um hübsch lineare Abfolgen von Commits zu erhalten. Das Commit-Protokoll des Repositorys wird durch Rebase eine ganze Ecke einfacher aussehen, weil Merge Commits vermieden werden.",
|
||||||
|
"",
|
||||||
|
"Schauen wir's uns mal in Aktion an ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Hier haben wir wieder zwei Branches; wie du siehst ist `bugFix` aktuell ausgewählt (sieht man am `*`).",
|
||||||
|
"",
|
||||||
|
"Wir würden jetzt gerne unsere Arbeit aus `bugFix` direkt auf den `master` packen. Das Ergebnis wäre, dass alle aktuellen Änderungen in `master` auch im Branch `bugFix` sind.",
|
||||||
|
"",
|
||||||
|
"Das machen wir mit dem Befehl `git rebase`:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Hammer! Was wir in `bugFix` gemacht haben ist jetzt oben auf `master` draufgepackt und wir haben eine schön lineare Abfolge von Commits bekommen.",
|
||||||
|
"",
|
||||||
|
"Commit `C3` existiert immer noch irgendwo (deswegen ist er blaß dargestellt) und `C3'` ist die \"Kopie\" die wir auf den `master` gepackt haben.",
|
||||||
|
"",
|
||||||
|
"Aber `master` ist jetzt nicht aktualisiert worden, lass uns das gerade noch nachholen ..."
|
||||||
|
],
|
||||||
|
"command": "git rebase master",
|
||||||
|
"beforeCommand": "git commit; git checkout -b bugFix C1; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Jetzt sind wir im `master`. Lass uns den mal auf `bugFix` rebasen ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"So! Da `master` ein Vorgänger von `bugFix` war konnte Git hier einfach den Bezeichner `master` auf denselben Commit schieben, auf den auch `bugFix` zeigt."
|
||||||
|
],
|
||||||
|
"command": "git rebase bugFix",
|
||||||
|
"beforeCommand": "git commit; git checkout -b bugFix C1; git commit; git rebase master; git checkout master"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um dieses Level abzuschließen musst du folgendes tun:",
|
||||||
|
"",
|
||||||
|
"* Einen neuen Branch namens `bugFix` auschecken",
|
||||||
|
"* Einen Commit machen",
|
||||||
|
"* Zurück zum `master` wechseln und noch einmal committen",
|
||||||
|
"* `bugFix` auschecken und auf den `master` rebasen",
|
||||||
|
"",
|
||||||
|
"Viel Erfolg!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,10 +3,12 @@ exports.level = {
|
||||||
"solutionCommand": "git commit ",
|
"solutionCommand": "git commit ",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"side\":{\"target\":\"C4\",\"id\":\"side\",\"remoteTrackingBranchID\":null},\"bugFix\":{\"target\":\"C6\",\"id\":\"bugFix\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C3\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"}},\"tags\":{\"v0\":{\"target\":\"C0\",\"id\":\"v0\",\"type\":\"tag\"},\"v1\":{\"target\":\"C3\",\"id\":\"v1\",\"type\":\"tag\"}},\"HEAD\":{\"target\":\"bugFix\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"side\":{\"target\":\"C4\",\"id\":\"side\",\"remoteTrackingBranchID\":null},\"bugFix\":{\"target\":\"C6\",\"id\":\"bugFix\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C3\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"}},\"tags\":{\"v0\":{\"target\":\"C0\",\"id\":\"v0\",\"type\":\"tag\"},\"v1\":{\"target\":\"C3\",\"id\":\"v1\",\"type\":\"tag\"}},\"HEAD\":{\"target\":\"bugFix\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Git Describe"
|
"en_US": "Git Describe",
|
||||||
|
"de_DE": "Git Describe"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Just commit once on bugFix when you're ready to move on"
|
"en_US": "Just commit once on bugFix when you're ready to move on",
|
||||||
|
"de_DE": "Committe nur einmal auf bugFix, wenn du soweit bist"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -71,6 +73,69 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Git Describe",
|
||||||
|
"",
|
||||||
|
"Weil Tags so super als \"Anker\" im Repository dienen können bietet Git einen Befehl um zu *beschreiben* wo du dich relativ zum nächsten \"Anker\" (also Tag) befindest. Und der heißt `git describe`.",
|
||||||
|
"",
|
||||||
|
"Er hilft dir dabei, dir einen Überblick zu verschaffen nachdem du viele Commits im Log zurück- oder vorgegangen bist; das kann vorkommen nachdem du ein `git bisect` (eine Fehlersuche) abgeschlossen hast oder wenn du dich an den Rechner eines Kollegen setzt, der gerade aus dem Urlaub gekommen ist."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Der Befehl ist folgendermaßen aufgebaut:",
|
||||||
|
"",
|
||||||
|
"`git describe <Ref-Name>`",
|
||||||
|
"",
|
||||||
|
"Dabei ist `<Ref-Name>` jeder beliebige Name, der einem Commit zugeordnet ist (Branch, Tag etc). Wenn du keinen angibst benutzt Git `HEAD`, also den aktuellen Checkout.",
|
||||||
|
"",
|
||||||
|
"Die Befehlsausgabe sieht so aus:",
|
||||||
|
"",
|
||||||
|
"`<Tag-Name>_<Anzahl Commits>_g<Hash>`",
|
||||||
|
"",
|
||||||
|
"`<Tag-Name>` ist dabei der nächstliegende Tag in den Vorgänger-Commits, `<Anzahl Commits>` zeigt an, wieviele Commits dieses Tag entfernt ist und `<Hash>` ist das SHA des Commits, auf den das Tag zeigt."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns das schnell an einem Beispiel an. Für den folgenden Baum:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Der Befehl `git describe master` würde folgendes ausgeben:",
|
||||||
|
"",
|
||||||
|
"`v1_2_gC2`",
|
||||||
|
"",
|
||||||
|
"Wohingegen `git describe side` dies ausgeben würde:",
|
||||||
|
"",
|
||||||
|
"`v2_1_gC4`"
|
||||||
|
],
|
||||||
|
"command": "git tag v2 C3",
|
||||||
|
"beforeCommand": "git commit; go -b side HEAD~1; gc; gc; git tag v1 C0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Das ist so ziemlich alles, was es über `git describe` zu wissen gibt. Versuch ein paar Orte in diesem Level damit auszugeben, um ein Gefühl dafür zu bekommen.",
|
||||||
|
"",
|
||||||
|
"Sobald du fertig bist, mach einfach einen Commit um den Level abzuschließen. Der geht auf's Haus. :P"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,12 +16,14 @@ exports.level = {
|
||||||
"name": {
|
"name": {
|
||||||
"ko": "딱 한개의 커밋만 가져오기",
|
"ko": "딱 한개의 커밋만 가져오기",
|
||||||
"en_US": "Grabbing Just 1 Commit",
|
"en_US": "Grabbing Just 1 Commit",
|
||||||
|
"de_DE": "Einen Commit pflücken",
|
||||||
"ja": "Grabbing Just 1 Commit",
|
"ja": "Grabbing Just 1 Commit",
|
||||||
"zh_CN": "只取一个提交",
|
"zh_CN": "只取一个提交",
|
||||||
"zh_TW": "只取一個 commit"
|
"zh_TW": "只取一個 commit"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember, interactive rebase or cherry-pick is your friend here",
|
"en_US": "Remember, interactive rebase or cherry-pick is your friend here",
|
||||||
|
"de_DE": "Vergiss nicht: hier kommst du mit interaktivem Rebase oder Cherry-Picking weiter",
|
||||||
"ja": "このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",
|
"ja": "このレベルではインタラクティブモードのrebaseやcherry-pickがクリアのカギです",
|
||||||
"ko": "대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",
|
"ko": "대화식 리베이스(rebase -i)나 or 체리픽(cherry-pick)을 사용하세요",
|
||||||
"zh_CN": "记住,交互式 rebase 或者 cherry-pick 会很有帮助",
|
"zh_CN": "记住,交互式 rebase 或者 cherry-pick 会很有帮助",
|
||||||
|
@ -67,6 +69,44 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Lokale Commit-Haufen",
|
||||||
|
"",
|
||||||
|
"Folgende Situation habe ich beim Entwickeln des öfteren: ich bin auf der Suche nach einem Bug, aber er ist echt schwer zu finden. Um ihm auf die Spur zu kommen schreibe ich mehrere Debug-Kommandos und print-Befehle in den Code.",
|
||||||
|
"",
|
||||||
|
"Die committe ich auch immer wieder, je weiter die Suche mich trägt; natürlich in einem lokalen Branch. Schließlich finde ich den Bug, fixe ihn und freue mich!",
|
||||||
|
"",
|
||||||
|
"Einziges Problem ist, dass ich diesen `bugFix` jetzt zurück in den `master` kriegen muss. Wenn ich einfach den `master` vorspule oder meinen Branch hinein merge, bekäme der `master` auch die ganzen Debug-Befehle, was nicht gewünscht ist. Das muss anders gehen ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Wir müssten Git sagen können, dass es nur einen Commit herüber kopieren soll. Das ist genauso wie die Level vorhin zum Code-Verschieben. Wir können dieselben Befehle benutzen:",
|
||||||
|
"",
|
||||||
|
"* `git rebase -i`",
|
||||||
|
"* `git cherry-pick`",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Da dies ein späterer Level ist überlasse ich es dir zu entscheiden, welchen Befehl du benutzen willst. Aber um da Level zu schaffen musst du irgendwie sicherstellen, dass `maste` den Commit bekommt, auf den `bugFix` zeigt."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
// INTL out of sync :(
|
// INTL out of sync :(
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
|
|
|
@ -20,12 +20,14 @@ exports.level = {
|
||||||
"name": {
|
"name": {
|
||||||
"ko": "커밋들 갖고 놀기",
|
"ko": "커밋들 갖고 놀기",
|
||||||
"en_US": "Juggling Commits",
|
"en_US": "Juggling Commits",
|
||||||
|
"de_DE": "Jonglieren mit Commits",
|
||||||
"ja": "Juggling Commits",
|
"ja": "Juggling Commits",
|
||||||
"zh_CN": "提交变换戏法",
|
"zh_CN": "提交变换戏法",
|
||||||
"zh_TW": "commit 的戲法"
|
"zh_TW": "commit 的戲法"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "The first command is git rebase -i HEAD~2",
|
"en_US": "The first command is git rebase -i HEAD~2",
|
||||||
|
"de_DE": "Der erste Befehl ist git rebase -i HEAD~2",
|
||||||
"ja": "最初に打つコマンドはgit rebase -i HEAD~2",
|
"ja": "最初に打つコマンドはgit rebase -i HEAD~2",
|
||||||
"ko": "첫번째 명령은 git rebase -i HEAD~2 입니다",
|
"ko": "첫번째 명령은 git rebase -i HEAD~2 입니다",
|
||||||
"zh_CN": "第一个命令是 'git rebase -i HEAD~2'",
|
"zh_CN": "第一个命令是 'git rebase -i HEAD~2'",
|
||||||
|
@ -73,6 +75,47 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Jonglieren mit Commits",
|
||||||
|
"",
|
||||||
|
"Eine weitere häufig vorkommende Situation: du hast einige Änderungen in `newImage` und weitere Änderungen in `caption`. Die Änderungen hängen voneineander ab, das heißt in diesem Fall `caption` ist ein Nachfolger von `newImage`.",
|
||||||
|
"",
|
||||||
|
"Nun kann es vorkommen, dass du einen früheren Commit verändern willst. In unserem Fall will die Design-Abteilung, dass die Abmessungen in `newImage` leicht verändert werden, obwohl das mitten in unserer History liegt!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um das zu schaffen gehen wir wie folgt vor:",
|
||||||
|
"",
|
||||||
|
"* Wir sortieren die Commits mit `git rebase -i` so um, dass der, den wir ändern wollen, ganz oben liegt.",
|
||||||
|
"* Wir verändern den Commit mit `git commit --amend`.",
|
||||||
|
"* Dann sortieren wir die Commit mit einem erneuten `git rebase -i` wieder in die alte Reihenfolge.",
|
||||||
|
"* Schließlich aktualisieren wir den `master` auf das Ende unseres fertigen Baums, um diesen Level abzuschließen.",
|
||||||
|
"",
|
||||||
|
"Es gibt sehr viele Wege um das Endziel dieses Levels zu erreichen (ich sehe, du schielst auf `cherry-pick`) und wir werden uns später noch andere ansehen. Aber für's erste lass uns diese Methode ausprobieren."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Beachte den geschilderten Zielzustand. Da wir die Commits zweimal umsortieren bekommen sie jedesmal ein Apostroph hinzugefügt (weil sie jedesmal kopiert werden). Ein weiteres Apostroph entsteht durch den `commit --amend`.",
|
||||||
|
"",
|
||||||
|
"Zuguterletzt noch eine Bemerkung: ich kann Level nun auf Struktur und Apostroph-Differenz prüfen. So lange wie dein `master` am Ende dieselbe Strukutr und Apostroph-Differenz aufweist wie der Ziel-`master`, ist der Level bestanden."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,12 +19,14 @@ exports.level = {
|
||||||
"name": {
|
"name": {
|
||||||
"ko": "커밋 갖고 놀기 #2",
|
"ko": "커밋 갖고 놀기 #2",
|
||||||
"en_US": "Juggling Commits #2",
|
"en_US": "Juggling Commits #2",
|
||||||
|
"de_DE": "Jonglieren mit Commits Teil 2",
|
||||||
"ja": "コミットをやりくりする その2",
|
"ja": "コミットをやりくりする その2",
|
||||||
"zh_CN": "提交交换戏法 #2",
|
"zh_CN": "提交交换戏法 #2",
|
||||||
"zh_TW": "commit 的戲法 #2"
|
"zh_TW": "commit 的戲法 #2"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Don't forget to forward master to the updated changes!",
|
"en_US": "Don't forget to forward master to the updated changes!",
|
||||||
|
"de_DE": "Vergiss nicht den master auf die aktuelle Version vorzuspulen",
|
||||||
"ja": "masterのポインタを先に進めることを忘れずに!",
|
"ja": "masterのポインタを先に進めることを忘れずに!",
|
||||||
"ko": "master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",
|
"ko": "master를 변경 완료한 커밋으로 이동(forward)시키는 것을 잊지 마세요!",
|
||||||
"zh_CN": "别忘记了将 master 快进到最新的更新上!",
|
"zh_CN": "别忘记了将 master 快进到最新的更新上!",
|
||||||
|
@ -74,6 +76,49 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Jonglieren mit Commits Teil 2",
|
||||||
|
"",
|
||||||
|
"Du solltest \"Jonglieren mit Commits\" (den vorherigen Level) bestanden haben, bevor du dich an diesem hier versuchst.",
|
||||||
|
"",
|
||||||
|
"Wie du im letzten Level gesehen hast haben wir `git rebase -i` genutzt, um die Commits neu anzuordnen. Sobald der Commit, den wir ändern wollte, ganz oben war, konnten wir das auch einfach mit `git commit --amend` tun. Danach haben wir die alte Reihenfolge wiederhergestellt.",
|
||||||
|
"",
|
||||||
|
"Das einzige Problem ist hier, dass da eine Menge Umsortieren stattfindet, was zu Rebase-Konflikten führen kann. Schauen wir uns also eine Methode mit `git cherry-pick` an."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Wie du dich erinnerst macht `git cherry-pick` eine Kopie des angegebenen Commits und fügt sie an `HEAD` an (es sei denn der Commit ist ein Vorgänger von `HEAD`).",
|
||||||
|
"",
|
||||||
|
"Hier eine kleine Demo zur Erinnerung:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Schick! Und weiter geht's."
|
||||||
|
],
|
||||||
|
"command": "git cherry-pick C2",
|
||||||
|
"beforeCommand": "git checkout -b bugFix; git commit; git checkout master; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"In diesem Level geht es also auch um das Ziel den Commit `C2` zu modifizieren, aber ohne `git rebase -i` zu benutzen. Ich überlass es dir herauszufinden, wie das gehen soll. :D",
|
||||||
|
"",
|
||||||
|
"Nicht vergessen, die genaue Anzahl von Kopien (d.h. Apostrophs) ist nicht ausschlaggebend, nur die Differenz. Der Level ist zum Beispiel auch gelöst, wenn dein fertiger Baum dieselbe Struktur wie der Ziel-Baum hat, aber *überall* ein Apostroph mehr aufweist."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,10 +3,12 @@ exports.level = {
|
||||||
"solutionCommand": "git tag v1 side~1;git tag v0 master~2;git checkout v1",
|
"solutionCommand": "git tag v1 side~1;git tag v0 master~2;git checkout v1",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C5\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"side\":{\"target\":\"C3\",\"id\":\"side\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C1\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C2\",\"C4\"],\"id\":\"C5\"}},\"tags\":{},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C5\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"side\":{\"target\":\"C3\",\"id\":\"side\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C1\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C2\",\"C4\"],\"id\":\"C5\"}},\"tags\":{},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Git Tags"
|
"en_US": "Git Tags",
|
||||||
|
"de_DE": "Git Tags"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "you can either check out the commit directly or simply checkout the tag!"
|
"en_US": "you can either check out the commit directly or simply checkout the tag!",
|
||||||
|
"de_DE": "Du kannst den Checkout entweder direkt auf den Commit oder das Tag machen."
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -60,6 +62,58 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Tags",
|
||||||
|
"",
|
||||||
|
"Wie du aus den vorhergehenden Levels weißt sind Branches einfach durch die Gegend zu schieben und zeigen of auf verschiedene Commits, während die Arbeit in ihnen fortschreitet. Ein Branch wird oft verändert, manchmal nur temporär, und ist ständig in Bewegung.",
|
||||||
|
"",
|
||||||
|
"Da das so ist fragst du dich vielleicht, ob es nicht eine Möglichkeit gibt, eine bestimmte Stelle in deiner Projekt-History *permanent* zu kennzeichnen. Kann man nicht zum Beispiel für große Releases und Meilensteine nicht einen Commit mit etwas festerem kennzeichnen, als mit einem Branch-Namen?",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Aber klar! In Git gibt es genau zu diesem Zweck Tags -- sie kennzeichnen einen Commit (ziemlich) permanent als Meilenstein oder ähnliches, und man kann sie ansprechen wie Branch-Namen.",
|
||||||
|
"",
|
||||||
|
"Noch viel wichtiger, Tags verändern nicht ihre Position wenn man Commits hinzufügt. Du kannst ein Tag nicht in diesem Sinne auschecken und dann Modifikationen darauf committen. Tags sind Anker im Commit-Baum, die bestimmte Stellen anzeigen.",
|
||||||
|
"",
|
||||||
|
"Lass uns anschauen wie Tags in der Praxis funktionieren."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Lass uns ein Tag bei `C1` anlegen und damit die Version 1 unseres Prototyps markieren."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Peng! Ziemlich einfach. Wir haben das Tag `v1` genannt und lassen es auf `C1` zeigen. Wenn du den Commit weglässt wir das Tag für den Commit erzeugt, auf den `HEAD` zeigt."
|
||||||
|
],
|
||||||
|
"command": "git tag v1 C1",
|
||||||
|
"beforeCommand": "git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level zu schaffen, erstelle einfach die Tags wie sie in der Zielbeschreibung stehen und mach dann einen Checkout auf `v1`. Beachte wie du dabei in den \"Detached HEAD\" Zustand gehst -- das liegt daran, dass du keine Commits direkt auf das `v1` Tag machen kannst.",
|
||||||
|
"",
|
||||||
|
"Im nächsten Level schauen wir uns dann interessantere Anwendungsfälle für Tags an."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,10 +7,14 @@ exports.level = {
|
||||||
},
|
},
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C3\",\"id\":\"bugFix\"},\"side\":{\"target\":\"C5\",\"id\":\"side\"},\"another\":{\"target\":\"C7\",\"id\":\"another\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C1\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C1\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C3\",\"id\":\"bugFix\"},\"side\":{\"target\":\"C5\",\"id\":\"side\"},\"another\":{\"target\":\"C7\",\"id\":\"another\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C1\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C1\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Cherry-pick Intro"
|
"en_US": "Cherry-pick Intro",
|
||||||
|
"de_DE": "Einführung Cherry-picking",
|
||||||
|
"zh_CN": "Cherry-pick Intro"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "git cherry-pick followed by commit names!"
|
"en_US": "git cherry-pick followed by commit names!",
|
||||||
|
"de_DE": "git cherry-pick gefolgt von Commit-Namen.",
|
||||||
|
"zh_CN": "git cherry-pick 跟提交对句名"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -23,7 +27,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"So far we've covered the basics of git -- committing, branching, and moving around in the source tree. Just these concepts are enough to leverage 90% of the power of git repositories and cover the main needs of developers.",
|
"So far we've covered the basics of git -- committing, branching, and moving around in the source tree. Just these concepts are enough to leverage 90% of the power of git repositories and cover the main needs of developers.",
|
||||||
"",
|
"",
|
||||||
"That remaining 10%, however, can be quite useful during complex workflows (or when you've gotten yourself into a bind). The next concept we're going to cover is \"moving work around\" -- in other words, its a way for developers to say \"I want this work here and that work here\" in precise, eloquent, flexible ways.",
|
"That remaining 10%, however, can be quite useful during complex workflows (or when you've gotten yourself into a bind). The next concept we're going to cover is \"moving work around\" -- in other words, it's a way for developers to say \"I want this work here and that work there\" in precise, eloquent, flexible ways.",
|
||||||
"",
|
"",
|
||||||
"This may seem like a lot, but it's a simple concept."
|
"This may seem like a lot, but it's a simple concept."
|
||||||
]
|
]
|
||||||
|
@ -69,6 +73,118 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## 转移工作区",
|
||||||
|
"",
|
||||||
|
"到现在我们已经学习了git的基础命令 -- commit, branch, checkout. 这些概念实现了git 90% 的功能, 同样也满足了开发者的主要需求 ",
|
||||||
|
"",
|
||||||
|
"然而, 剩余的10% 可能在处理复杂的工作流时(或者当你陷入困惑时), 非常的重要. 我们会在下一个概念中涉及'转移工作区', 换句话说, 这是开发者表达'我想要把这个工作放这里, 那个工作也放这里', 精确的说, 这是很灵活的方式 ",
|
||||||
|
"",
|
||||||
|
"看起来内容很多, 其实概念相当简单"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Cherry-pick",
|
||||||
|
"",
|
||||||
|
"本系列的第一个命令是`git cherry-pick`, 命令形式为: ",
|
||||||
|
"",
|
||||||
|
"* `git cherry-pick <Commit1> <Commit2> <...>`",
|
||||||
|
"",
|
||||||
|
"这是一种很直接的推进方式 -- 如果你想将一些提交复制到你当前的位置`HEAD`下面, 我个人喜欢`cherry-pick` 的原因是, 其概念非常简单 ",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"现在有一个仓库, 我们想将`side`分支下的工作复制到`master`分支, 我们可以通过`rebase`完成这一点(已经学过了哈), 但是这里我们想通过`cherry-pick`来完成."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"这是它啦, 我们需要的是提交对象`C2` 和 `C4` ,所以 git 将被它们抓取到当前分支下了. 就是这么简单!"
|
||||||
|
],
|
||||||
|
"command": "git cherry-pick C2 C4",
|
||||||
|
"beforeCommand": "git checkout -b side; git commit; git commit; git commit; git checkout master; git commit;"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"请完成这节测试, 只需要简单的将分支的工作复制到 master. 如果想看我们所需要的提交对象, 你可以打开虚拟目标窗口(`show goal`)",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Inhalte verschieben",
|
||||||
|
"",
|
||||||
|
"Bis jetzt haben wir uns die Grundlagen von Git angeschaut -- comitten, verzweigen und sich im Commit-Baum bewegen. Nur damit lässt sich schon 90% der Macht von Git-Repositories nutzen und die meisten Anforderungen von Entwicklern erfüllen.",
|
||||||
|
"",
|
||||||
|
"Die übrigen 10% jedoch können in komplexeren Abläufen sehr hilfreich sein (oder wenn man sich in eine schwierige Lage manövriert hat). Das nächste was wir uns anschauen, ist, Inhalte durch den Commit-Baum zu schieben. Es gibt dem Entwickler die Möglichkeit in präziser, eloquenter Manier zu sagen \"Ich will diese Inhalte hier und diese dort haben\".",
|
||||||
|
"",
|
||||||
|
"Das klingt vielleicht nach einer Menge, aber es ist sehr einfach."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## git cherry-pick",
|
||||||
|
"",
|
||||||
|
"Der erste Befehl in dieser Serie ist `git cherry-pick`. Er sieht so aus:",
|
||||||
|
"",
|
||||||
|
"* `git cherry-pick <Commit1> <Commit2> <...>`",
|
||||||
|
"",
|
||||||
|
"Er ist eine einfache Möglichkeit um auszudrücken, dass du eine Folge von Commits unter deinen aktuellen Checkout (also `HEAD`) hängen möchtest. Ich persönlich liebe `cherry-pick`, weil es wenig Magic enthält und einfach zu verstehen ist.",
|
||||||
|
"",
|
||||||
|
"Schauen wir's uns mal an.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Hier haben wir ein Repository mit einigem Zeugs im Branch `side`, das wir in den Branch `master` kopieren wollen. Das könnten wir mit einem Rebase machen (wie bereits gesehen), aber schauen wir mal wie das mit `cherry-pick` geht."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Das war's! Wir wollten die commits `C2` und `C4` und Git hat die einfach unter unseren aktuellen Checkout kopiert. So einfach ist das."
|
||||||
|
],
|
||||||
|
"command": "git cherry-pick C2 C4",
|
||||||
|
"beforeCommand": "git checkout -b side; git commit; git commit; git commit; git checkout master; git commit;"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level zu schaffen musst du einfach nur einige Commits aus den drei gezeigten Branches in den `master` kopieren. Der Zielbaum zeigt dir, welche.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,11 +6,13 @@ exports.level = {
|
||||||
"en_US": "Detach yo' HEAD",
|
"en_US": "Detach yo' HEAD",
|
||||||
"zh_CN": "分离HEAD",
|
"zh_CN": "分离HEAD",
|
||||||
"zh_TW": "分離HEAD"
|
"zh_TW": "分離HEAD"
|
||||||
|
"de_DE": "Den Kopf abtrennen",
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Use the label (hash) on the commit for help!",
|
"en_US": "Use the label (hash) on the commit for help!",
|
||||||
"zh_CN": "使用提交记录上的标签(hash)来求助!",
|
"de_DE": "Benutze den Bezeichner (den Hash) des Commits.",
|
||||||
"zh_TW": "使用 commit 上的標籤(hash)來幫助你!"
|
"zh_TW": "使用 commit 上的標籤(hash)來幫助你!"
|
||||||
|
"zh_CN": "使用提交记录上的标签(hash)来求助!"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -91,6 +93,84 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Navigation durch Git",
|
||||||
|
"",
|
||||||
|
"Bevor wir uns einige fortgeschrittene Konzepte in Git ansehen ist es wichtig, verschiedene Wege zum Navigieren durch den Commit-Baum, der das Projekt enthält, zu kennen.",
|
||||||
|
"",
|
||||||
|
"Sobald du das drauf hast, vergrößern sich deine Möglichkeiten in allen anderen Git-Befehlen.",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## HEAD",
|
||||||
|
"",
|
||||||
|
"Erst mal müssen wir über `HEAD` reden. `HEAD` ist ein Alias für den Commit, der gerade ausgecheckt ist -- es ist im Prinzip der Commit, an den du deinen nächsten Commit hängst.",
|
||||||
|
"",
|
||||||
|
"`HEAD` zeigt immer auf den neuesten Commit. Die meisten Git-Befehle, die den Baum verändern, fangen damit an dass sie `HEAD` verschieben.",
|
||||||
|
"",
|
||||||
|
"Normalerweise zeigt `HEAD` auf einen Branch-Namen (z.B. `bugFix`). Wenn du einen Commit machst, wird `bugFix` auf diesen Commit geschoben, und `HEAD` (da es auf `bugFix` zeigt) automatisch auch."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns das mal in Aktion an. Wir werden hier `HEAD` vor und nach dem Commit anzeigen."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Siehst du? `HEAD` war die ganze Zeit unter `master` versteckt."
|
||||||
|
],
|
||||||
|
"command": "git checkout C1; git checkout master; git commit; git checkout C2",
|
||||||
|
"beforeCommand": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"### HEAD abkoppeln",
|
||||||
|
"",
|
||||||
|
"`HEAD` abzukoppeln bedeutet, es direkt an einen bestimmten Commit zu hängen, anstatt an einen Branch. Wir gelangen dadurch in den \"detached HEAD state\". So sieht's vorher aus:",
|
||||||
|
"",
|
||||||
|
"`HEAD` -> `master` -> `C1`",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Und jetzt:",
|
||||||
|
"",
|
||||||
|
"`HEAD` -> `C1`"
|
||||||
|
],
|
||||||
|
"command": "git checkout C1",
|
||||||
|
"beforeCommand": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level abzuschließen, lass uns mal `HEAD` von `bugFix` abkoppeln und an den Commit hängen.",
|
||||||
|
"",
|
||||||
|
"Gib den Commit mit seinem Hash an. Der Hash jedes Commits steht in dem Kreis, der den Commit darstellt."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"zh_CN": {
|
"zh_CN": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,10 +7,13 @@ exports.level = {
|
||||||
},
|
},
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C5\",\"id\":\"master\"},\"overHere\":{\"target\":\"C1\",\"id\":\"overHere\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C5\",\"id\":\"master\"},\"overHere\":{\"target\":\"C1\",\"id\":\"overHere\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "you can use either branches or relative refs (HEAD~) to specify the rebase target"
|
"en_US": "you can use either branches or relative refs (HEAD~) to specify the rebase target",
|
||||||
|
"de_DE": "Du kannst entweder Branches oder relative Ref-Angaben (z.B. HEAD~) benutzen, um das Ziel des Rebase anzugeben."
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Interactive Rebase Intro"
|
"en_US": "Interactive Rebase Intro",
|
||||||
|
"de_DE": "Einführung Interactive Rebase",
|
||||||
|
"zh_CN": "Rebase 交互命令介绍 "
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -49,9 +52,9 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"* You can reorder commits simply by changing their order in the UI (in our window this means dragging and dropping with the mouse).",
|
"* You can reorder commits simply by changing their order in the UI (in our window this means dragging and dropping with the mouse).",
|
||||||
"* You can choose to completely omit some commits. This is designated by `pick` -- toggling `pick` off means you want to drop the commit.",
|
"* You can choose to completely omit some commits. This is designated by `pick` -- toggling `pick` off means you want to drop the commit.",
|
||||||
"* Lastly, you can squash commits. Unfortunately our levels don't support this for a few logistical reasons, so I\"ll skip over the details of this. Long story short though -- it allows you to combine commits.",
|
"* Lastly, you can squash commits. Unfortunately our levels don't support this for a few logistical reasons, so I'll skip over the details of this. Long story short, though -- it allows you to combine commits.",
|
||||||
"",
|
"",
|
||||||
"Great! Lets see an example"
|
"Great! Let's see an example."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -77,6 +80,137 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Interactive Rebase",
|
||||||
|
"",
|
||||||
|
"如果你知道你所需要的提交对象(相应的hash), 那用Git cherry-pick 就非常方便了 -- 很难有简单的方式了",
|
||||||
|
"",
|
||||||
|
"But what about the situation where you don't know what commits you want? Thankfully git has you covered there as well! We can use interactive rebasing for this -- it's the best way to review a series of commits you're about to rebase.",
|
||||||
|
"但是如果你不清楚你想要的提交对象的hash呢? 幸好git 帮你想到了这一点, 我们可以利用交互rebase -- 如果你想衍合一系列的提交, 这就是最方便的方法了",
|
||||||
|
"",
|
||||||
|
"让我们看看细节.."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"交互式rebase 指的是rebase 后跟一个参数: `-i`",
|
||||||
|
"",
|
||||||
|
"如果你包含了这个选项, git 会开启一个UI 并 展示出将要被复制到目标的提交对象, 它也会显示它们的提交hash 和 信息",
|
||||||
|
"",
|
||||||
|
"真实的git , UI 窗口指的是在类似于vim的文本编辑器中打开一个文件. 考虑到我们的目标, 我建立了一个小型的会话窗口以完成相同的事儿."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"当rebase会话窗口打开时, 你能做3件事:",
|
||||||
|
"",
|
||||||
|
"* 你可以在UI中做 提交对象的排序(在我们的窗口中, 这意味着你可以拖放完成这点)",
|
||||||
|
"* 你可以忽略某些提交 -- pick 会变暗",
|
||||||
|
"* 最后, 你可以合并提交. 遗憾的是我们的课程不支持此功能.",
|
||||||
|
"",
|
||||||
|
"好! 看看例子"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"当你点这个按钮时, 一个交互式的rebase窗口就会出现. 对提交对象做个排序, 再看看结果"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"按照你指定的方式, git 克隆了这些提交"
|
||||||
|
],
|
||||||
|
"command": "git rebase -i HEAD~4 --aboveAll",
|
||||||
|
"beforeCommand": "git commit; git commit; git commit; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"要完成本节, 做一个交互式的rebase , 实现虚拟目标窗口中提示的提交顺序. 记住, 你随时都可以用`undo`, `reset`修复你的错误"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Interaktiver Rebase",
|
||||||
|
"",
|
||||||
|
"Cherry-pick ist großartig wenn du genau weißt, welche Commits du willst (_und_ ihre jeweiligen Hashes kennst) -- es ist dann schwer an Einfachheit zu überbieten.",
|
||||||
|
"",
|
||||||
|
"Aber wie sieht es aus, wenn du die Commits nicht genau kennst, die du brauchst? Zum Glück bietet Git auch dafür eine Lösung an. Das können wir mit interaktivem Rebase machen -- die beste Art sich eine Serie von Commits in einem Rebase genau anzusehen.",
|
||||||
|
"",
|
||||||
|
"Schauen wir uns die Details an ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Interaktives Rebase bedeutet einfach nur, dass man dem `rebase` Befehl die Option `-i` hinzufügt.",
|
||||||
|
"",
|
||||||
|
"Wenn du das machst, zeigt Git dir jeden einzelnen Commit, der durch den Rebase kopiert werden würde. Es zeigt dir die Hashes und Kommentare, was gut ist um einen Überblick zu bekommen.",
|
||||||
|
"",
|
||||||
|
"In echtem Git besteht dieser Dialog daraus, die Commits in einem Text-Editor angezeigt zu bekommen. Für unsere Zwecke hab ich ein kleines Dialog-Fenster gebaut, dass sich ähnlich verhält."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Wenn sich der Dialog für den interaktiven Rebase öffnet, kannst du drei Dinge tun:",
|
||||||
|
"",
|
||||||
|
"* Du kannst die Reihenfolge der Commits durch Ziehen und Ablegen ändern.",
|
||||||
|
"* Du kannst Git sagen, einen Commit beim Rebase zu ignorieren -- im Dialog durch die Schaltfläche `pick` dargestellt.",
|
||||||
|
"* Außerdem kannst du Commit zusammenfassen (squash). Leider wird das hier nicht unterstützt, aber in echtem Git fasst es Commits zu einem zusammen.",
|
||||||
|
"",
|
||||||
|
"Super! Schauen wir uns ein Beispiel an."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Wenn du die Schaltfläche anklickst wird sich der Rebase-Dialog öffnen. Veränder die Reihenfolge der Commits oder klick bei einigen auf `pick` und schau dir das Ergebnis an."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Bämm! Git hat die Commits genau so kopiert, wie du es ausgewählt hast."
|
||||||
|
],
|
||||||
|
"command": "git rebase -i HEAD~4 --aboveAll",
|
||||||
|
"beforeCommand": "git commit; git commit; git commit; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um dieses Level zu schaffen mach einen interaktiven Rebase, um genau doie Reihenfolge zu erzeugen die im Ziel-Baum angezeigt wird. Denk daran, dass du jederzeit mit `undo` oder `reset` Fehler rückgängig machen kannst. :D"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,12 @@ exports.level = {
|
||||||
"en_US": "Relative Refs (^)",
|
"en_US": "Relative Refs (^)",
|
||||||
"zh_CN": "相对引用(^)",
|
"zh_CN": "相对引用(^)",
|
||||||
"zh_TW": "相對引用(^)"
|
"zh_TW": "相對引用(^)"
|
||||||
|
"de_DE": "Relative Referenzen (^)",
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember the Caret (^) operator!",
|
"en_US": "Remember the Caret (^) operator!",
|
||||||
"zh_CN": "记住插入(^)操作符!",
|
"de_DE": "Denk an den Dach-Operator (^)!",
|
||||||
|
"zh_CN": "记住插入(^)操作符!"
|
||||||
"zh_TW": "不要忘記插入(^) 符號!"
|
"zh_TW": "不要忘記插入(^) 符號!"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
|
@ -88,6 +90,81 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Relative Referenzen",
|
||||||
|
"",
|
||||||
|
"Es kann etwas mühselig werden, sich in einem Commit-Baum mittels Angabe der Hashes zu bewegen. Im echten Leben hat man normalerweise keine hübsche Visualisierung des Baumes neben seinem Terminal, also benutzt man `git log` um die Hashes zu sehen.",
|
||||||
|
"",
|
||||||
|
"Außerdem sind die echten Hashes sehr viel länger und nicht fortlaufend nummeriert. Beispielsweise heißt der Hash, mit dem ich den letzten Level committet habe, in echt `fed2da64c0efc5293610bdd892f82a58e8cbc5d8`. Nicht gerade einprägsam ...",
|
||||||
|
"",
|
||||||
|
"Zum Glück ist Git intelligent wenn es um die Hashes geht. Du musst nur soviele Zeichen eines Hashes angeben, bis der Hash eindeutig ist. Ich kann also `fed2` eingeben anstatt die komplette Zeichenkette tippen zu müssen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Wie ich schon sagte: Commits über ihren Hash zu referenzieren ist nicht gerade der bequemste Weg. Weshalb es in Git relative Referenzen gibt. Welche super sind!",
|
||||||
|
"",
|
||||||
|
"Mit relativen Referenzen kann man bei einem leicht zu merkenden Bezeichner anfangen (zum Beispiel dem Branch-Namen `bugFix` oder der Referenz `HEAD`) und sich von dort vorarbeiten.",
|
||||||
|
"",
|
||||||
|
"Relative Referenzierung von Commits kann komplex sein, aber wir starten mit zwei einfachen Beispielen:",
|
||||||
|
"",
|
||||||
|
"* Geh einen Commit zurück mit `^`",
|
||||||
|
"* Geh eine bestimmte Anzahl von Commits zurück mit `~<Anzahl>`"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns zuerst den Dach-Operator (`^`) an. Jedes mal wenn du ihn hinter einen Referenz-Namen setzt, sagst du Git damit, dass es zum Vorgänger des angegebenen Commits gehen soll.",
|
||||||
|
"",
|
||||||
|
"Das heißt `master^` ist gleichbedeutend mit \"direkter Vorgänder des Commits, auf den `master` zeigt\".",
|
||||||
|
"",
|
||||||
|
"`master^^` ist also der Vorgänger des Vorgängers von `master`.",
|
||||||
|
"",
|
||||||
|
"Wir checken jetzt mal den Commit vor `master` aus:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Bämm! Fertig. Einfacher, als den Commit-Hash zu tippen (oder zu kopieren)."
|
||||||
|
],
|
||||||
|
"command": "git checkout master^",
|
||||||
|
"beforeCommand": "git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Du kannst auch `HEAD` als Basis für relative Referenzen benutzen. Lass uns das ein paar Mal verwenden, um uns im Commit-Baum nach oben zu bewegen."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Das war einfach. Wir reisen mit `HEAD^` in der Zeit zurück."
|
||||||
|
],
|
||||||
|
"command": "git checkout C3; git checkout HEAD^; git checkout HEAD^; git checkout HEAD^",
|
||||||
|
"beforeCommand": "git commit; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um dieses Level abzuschließen musst du den direkten Vorgänger von `bugFix` auschecken. Dadurch wirst du `HEAD` von `bugFix` abkoppeln.",
|
||||||
|
"",
|
||||||
|
"Du kannst natürlich den Hash angeben, aber versuch doch relative Referenzen zu benutzen!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"zh_CN": {
|
"zh_CN": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,12 @@ exports.level = {
|
||||||
"en_US": "You'll need to use at least one direct reference (hash) to complete this level",
|
"en_US": "You'll need to use at least one direct reference (hash) to complete this level",
|
||||||
"zh_CN": "这一关至少要用到一次直接引用(hash)",
|
"zh_CN": "这一关至少要用到一次直接引用(hash)",
|
||||||
"zh_TW": "這一關至少要用到一次直接參考(hash)"
|
"zh_TW": "這一關至少要用到一次直接參考(hash)"
|
||||||
|
"de_DE": "Du musst mindestens einen Hash benutzen, um dieses Level zu schaffen",
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Relative Refs #2 (~)",
|
"en_US": "Relative Refs #2 (~)",
|
||||||
"zh_CN": "相对引用2(~)",
|
"de_DE": "Relative Referenzen #2 (~)",
|
||||||
|
"zh_CN": "相对引用2(~)"
|
||||||
"zh_TW": "相對引用二(~)"
|
"zh_TW": "相對引用二(~)"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
|
@ -82,6 +84,74 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Der \"~\"-Operator",
|
||||||
|
"",
|
||||||
|
"Nehem wir an du willst viele Schritte im Commit-Baum zurückgehen. Dann wird es schnell mühsam immer wieder `^` einzugeben; deswegen gibt es in Git den Tilde-Operator `~`.",
|
||||||
|
"",
|
||||||
|
"Der Tilde-Operator akzeptiert optional eine Zahl, mit der du angeben kannst vieviele Vorgänger zu zurückgehen willst. Keine Anzahl anzugeben bewirkt dasselbe wie `~1`."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Geben wir mit `~` an wiviele Commits wir zurückgehen wollen"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Peng! So einfach -- relative Referenzen sind super."
|
||||||
|
],
|
||||||
|
"command": "git checkout HEAD~4",
|
||||||
|
"beforeCommand": "git commit; git commit; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Erzwungene Branches",
|
||||||
|
"",
|
||||||
|
"Du bist jetzt Experte in Sachen relative Referenzen, also lass sie uns mal richtig einsetzen.",
|
||||||
|
"",
|
||||||
|
"Das Verschieben von Branches ist einer der häufigsten Anwendungsfälle dafür. Du kannst einen Branchnamen direkt auf einen bestimmten Commit setzen (_ohne_ ihne vorher ausgecheckt haben zu müssen!) indem du den Parameter `-f` benutzt. So in etwa:",
|
||||||
|
"",
|
||||||
|
"`git branch -f master HEAD~3`",
|
||||||
|
"",
|
||||||
|
"Das bewegt (erzwungenermaßen) den `master` auf den Commit drei Vorgänger vor `HEAD`."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns das mal in Aktion an:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Das war's schon! Relative Referenzen ermüglichen es uns den Commit `C1` sehr einfach anzugeben und `git branch -f` ermöglicht es uns, den Branch sehr schnell auf diesen Commit zu setzen."
|
||||||
|
],
|
||||||
|
"command": "git branch -f master HEAD~3",
|
||||||
|
"beforeCommand": "git commit; git commit; git commit; git checkout -b bugFix"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Jetzt wo du relative Referenzen und erzwungenes Branching in Kombination gesehen hast können wir damit den nächsten Level bewältigen.",
|
||||||
|
"",
|
||||||
|
"Bewege `HEAD`, `master` und `bugFix` an die jeweils angegebenen Positionen, um diesen Level abzuschließen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"zh_CN": {
|
"zh_CN": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@ exports.level = {
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"},\"pushed\":{\"target\":\"C2\",\"id\":\"pushed\"},\"local\":{\"target\":\"C3\",\"id\":\"local\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"local\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"},\"pushed\":{\"target\":\"C2\",\"id\":\"pushed\"},\"local\":{\"target\":\"C3\",\"id\":\"local\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"local\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Reversing Changes in Git",
|
"en_US": "Reversing Changes in Git",
|
||||||
|
"de_DE": "Änderungen in Git rückgängig machen",
|
||||||
"ja": "変更を元に戻す",
|
"ja": "変更を元に戻す",
|
||||||
"fr_FR": "Annuler des changements avec Git",
|
"fr_FR": "Annuler des changements avec Git",
|
||||||
"ko": "Git에서 작업 되돌리기",
|
"ko": "Git에서 작업 되돌리기",
|
||||||
|
@ -13,6 +14,7 @@ exports.level = {
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Notice that revert and reset take different arguments.",
|
"en_US": "Notice that revert and reset take different arguments.",
|
||||||
|
"de_DE": "Beachte, dass revert und reset unterschiedliche Argumente benötigen",
|
||||||
"fr_FR": "",
|
"fr_FR": "",
|
||||||
"zh_CN": "注意revert和reset使用不同的参数。",
|
"zh_CN": "注意revert和reset使用不同的参数。",
|
||||||
"zh_TW": "注意 revert 和 reset 使用不同的參數。",
|
"zh_TW": "注意 revert 和 reset 使用不同的參數。",
|
||||||
|
@ -83,6 +85,69 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Änderungen in Git rückgängig machen",
|
||||||
|
"",
|
||||||
|
"Es gibt viele Möglichkeiten, Änderungen in Git zurückzunehmen. Und ebenso wie das Committen hat auch das rückgängig Machen eine Basis-Komponente (Dateien und Inhalte vormerken) und einen übergeordneten Aspekt (wie die Änderungen tatsächlich zurückgenommen werden). Diese Applikation beschäftigt sich wiederum mit den übergeordneten Vorgängen.",
|
||||||
|
"",
|
||||||
|
"Es gibt grundsätzlich zwei Arten in Git etwas rückgängig zu machen -- einerseits `git reset` und andererseit `git revert`. Wir schauen uns beide mal an.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"## Git Reset",
|
||||||
|
"",
|
||||||
|
"`git reset` nimm Änderungen zurück, indem es eine Branch-Referenz auf einen anderen Commit setzt. Es ist ein bisschen (aber nicht wirklich) wie \"Geschichte umschreiben\"; `git reset` bewegt einen Branch auf einen anderen Commit, als hätte er nie anders ausgesehen.",
|
||||||
|
"",
|
||||||
|
"Schauen wir, wie das aussieht:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Schick! Git hat den `master` einfach auf `C1` gesetzt; unser lokales Repository sieht nun so aus, als hätte `C2` nie stattgefunden."
|
||||||
|
],
|
||||||
|
"command": "git reset HEAD~1",
|
||||||
|
"beforeCommand": "git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"## Git Revert",
|
||||||
|
"",
|
||||||
|
"Obwohl `git reset` super im lokalen Kontext funktioniert, ist der Ansatz vom \"Umschreiben\" der Commit-Geschichte nicht geeignet für Branches, die auf einem Server liegen und auch von anderen benutzt werden.",
|
||||||
|
"",
|
||||||
|
"Um Änderungen rückgängig zu machen und das mit anderen zu *teilen* müssen wir `git revert` benutzen. Schauen wir uns das in Aktion an."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Komisch, es ist ein neuer Commit entstanden. Das liegt daran, dass `C2'` genau die *Änderungen* enthält, die die Änderungen aus `C2` aufheben.",
|
||||||
|
"",
|
||||||
|
"Durch Reverten kannst du das Zurücknehmen von Änderungen mit anderen teilen."
|
||||||
|
],
|
||||||
|
"command": "git revert HEAD",
|
||||||
|
"beforeCommand": "git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level abzuschließen musst du sowohl auf `local` also auch auf `pushed` jeweils die zwei letzten Commits zurücknehmen.",
|
||||||
|
"",
|
||||||
|
"Vergiss nicht, dass `pushed` auch auf einem Server liegt und `local` ein rein lokaler Branch ist -- das sollte dir helfen, die richtige Methode zu wählen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,6 +9,7 @@ exports.level = {
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C3\",\"id\":\"bugFix\"},\"side\":{\"target\":\"C6\",\"id\":\"side\"},\"another\":{\"target\":\"C7\",\"id\":\"another\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C0\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C5\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C3\",\"id\":\"bugFix\"},\"side\":{\"target\":\"C6\",\"id\":\"side\"},\"another\":{\"target\":\"C7\",\"id\":\"another\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C0\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C5\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Rebasing over 9000 times",
|
"en_US": "Rebasing over 9000 times",
|
||||||
|
"de_DE": "10000 Rebases unter dem `HEAD`",
|
||||||
"ko": "9천번이 넘는 리베이스",
|
"ko": "9천번이 넘는 리베이스",
|
||||||
"ja": "Rebasing over 9000 times",
|
"ja": "Rebasing over 9000 times",
|
||||||
"zh_CN": "N次Rebase",
|
"zh_CN": "N次Rebase",
|
||||||
|
@ -16,6 +17,7 @@ exports.level = {
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember, the most efficient way might be to only update master at the end...",
|
"en_US": "Remember, the most efficient way might be to only update master at the end...",
|
||||||
|
"de_DE": "Nicht vergessen: die effizienteste Möglichkeit könnte sein, schließlich einfach nur den master zu aktualisieren ...",
|
||||||
"ja": "最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",
|
"ja": "最も効率的なやり方はmasterを最後に更新するだけかもしれない・・・",
|
||||||
"ko": "아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",
|
"ko": "아마도 master를 마지막에 업데이트하는 것이 가장 효율적인 방법일 것입니다...",
|
||||||
"zh_CN": "记住,最后更新master分支可能是最高效的方法。",
|
"zh_CN": "记住,最后更新master分支可能是最高效的方法。",
|
||||||
|
@ -32,7 +34,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.",
|
"Man, we have a lot of branches going on here! Let's rebase all the work from these branches onto master.",
|
||||||
"",
|
"",
|
||||||
"Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.",
|
"Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, and so on, all in order.",
|
||||||
"",
|
"",
|
||||||
"If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"
|
"If you mess up along the way, feel free to use `reset` to start over again. Be sure to check out our solution and see if you can do it in fewer commands!"
|
||||||
]
|
]
|
||||||
|
@ -40,6 +42,25 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Mehrere Branches rebasen",
|
||||||
|
"",
|
||||||
|
"Wow, wir haben hier ja eine Menge Branches! Lass uns mal die ganze Arbeit, die in diesen Branches steckt, auf den `master` packen, um sie auf Stand zu bringen.",
|
||||||
|
"",
|
||||||
|
"Die Führungsetage macht die Sache allerdings etwas trickreicher -- die möchten, dass alle Commits in aufsteigender Reihenfolge geordnet sind. Das heißt unser fertiger Baum sollte `C7` ganz unten haben, darüber `C6` und so weiter und so fort.",
|
||||||
|
"",
|
||||||
|
"Upper management is making this a bit trickier though -- they want the commits to all be in sequential order. So this means that our final tree should have `C7'` at the bottom, `C6'` above that, etc etc, etc all in order.",
|
||||||
|
"Wenn du irgendwo einen Fehler machst, benutz ruhig `reset` um wieder von vorne anzufangen oder `undo` um einen Schrit zurückzugehen. Schau dir die Lösung an und versuch es in weniger Schritten hinzubekommen, als die."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,12 +9,14 @@ exports.level = {
|
||||||
"name": {
|
"name": {
|
||||||
"ko": "브랜치 스파게티",
|
"ko": "브랜치 스파게티",
|
||||||
"en_US": "Branch Spaghetti",
|
"en_US": "Branch Spaghetti",
|
||||||
|
"de_DE": "Branch-Spaghetti",
|
||||||
"ja": "ブランチスパゲッティ",
|
"ja": "ブランチスパゲッティ",
|
||||||
"zh_CN": "分支浆糊",
|
"zh_CN": "分支浆糊",
|
||||||
"zh_TW": "分支漿糊"
|
"zh_TW": "分支漿糊"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Make sure to do everything in the proper order! Branch one first, then two, then three",
|
"en_US": "Make sure to do everything in the proper order! Branch one first, then two, then three",
|
||||||
|
"de_DE": "Stelle sicher, dass du alles in der richtigen Reihenfolge machst! Branche erst one, dann two, dann three.",
|
||||||
"ja": "全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",
|
"ja": "全て正しい順番で処理すること!oneが最初で、次がtwo、最後にthreeを片付ける。",
|
||||||
"ko": "이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",
|
"ko": "이 문제를 해결하는 방법은 여러가지가 있습니다! 체리픽(cherry-pick)이 가장 쉽지만 오래걸리는 방법이고, 리베이스(rebase -i)가 빠른 방법입니다",
|
||||||
"zh_CN": "确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`",
|
"zh_CN": "确保你是按照正确的顺序来操作!先操作分支 `one`, 然后 `two`, 最后才是 `three`",
|
||||||
|
@ -41,6 +43,26 @@ exports.level = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Branch-Spaghetti",
|
||||||
|
"",
|
||||||
|
"Puh! Wir haben ein ganz schön schweres Ziel für dieses Level.",
|
||||||
|
"",
|
||||||
|
"Wir haben hier einen `master`, der ein paar Commits weiter ist als die Branche `one`, `two` und `three`. Aus welchem Grund auch immer müssen wir diese drei anderen Branches mit modifizierten Versionen der paar letzten Commits von `master` aktualisieren.",
|
||||||
|
"",
|
||||||
|
"Branch `one` benötigt eine Umsortierung und `C5` muss gelöscht werden. `two` muss nur umsortiert werden und `three` braucht nur einen Commit!",
|
||||||
|
"",
|
||||||
|
"Ich lass dich diese Aufgabe selbst lösen -- schau dir hinterher auf jeden Fall die Lösung mit `show solution` an."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"ja": {
|
"ja": {
|
||||||
"childViews": [
|
"childViews": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,10 +2,14 @@ exports.level = {
|
||||||
"goalTreeString": '{"branches":{"master":{"target":"C1","id":"master","remoteTrackingBranchID":"o/master"},"o/master":{"target":"C1","id":"o/master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"target":"C1","id":"master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"}}}',
|
"goalTreeString": '{"branches":{"master":{"target":"C1","id":"master","remoteTrackingBranchID":"o/master"},"o/master":{"target":"C1","id":"o/master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"},"originTree":{"branches":{"master":{"target":"C1","id":"master","remoteTrackingBranchID":null}},"commits":{"C0":{"parents":[],"id":"C0","rootCommit":true},"C1":{"parents":["C0"],"id":"C1"}},"HEAD":{"target":"master","id":"HEAD"}}}',
|
||||||
"solutionCommand": "git clone",
|
"solutionCommand": "git clone",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Clone Intro"
|
"en_US": "Clone Intro",
|
||||||
|
"de_DE": "Clone Einführung",
|
||||||
|
"zh_CN": "Clone Intro"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Just git clone!"
|
"en_US": "Just git clone!",
|
||||||
|
"de_DE": "Einfach git clone ausführen!",
|
||||||
|
"zh_CN": "Just git clone!"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -64,6 +68,119 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Remotes",
|
||||||
|
"",
|
||||||
|
"远程仓库并不复杂, 在如今的云计算的世界 很容易想到 git remotes背后有很多魔幻, 但是它们只是你的仓库到另个一台计算机上的拷贝. 你可以通过因特网与这台计算机通话 -- 传递后退和前进的提交对象",
|
||||||
|
"",
|
||||||
|
"话虽如些, 远程仓库却有一系列强大的属性",
|
||||||
|
"",
|
||||||
|
"- 首先, 远仓是一个强大的备份. 本地仓库也有恢复文件的能力, 但所有的信息都是保存在本地的. 即使你丢失了本地数据, 你仍可以通过远端仓库拷贝拿回你丢失的数据 ",
|
||||||
|
"",
|
||||||
|
"- 更重要的是, 远端让代码社交化了! 现在你的项目被白拷贝到别的地方了, 你的朋友可以更容易的为你的项目做贡献(或者pull 最新的变更)",
|
||||||
|
"",
|
||||||
|
"现在使用网站来可视化远端仓库变得越发流行(像 [Github](https://github.com/) or [Phabricator](http://phabricator.org/)), 但远库是这些工具的基石, 理解其概念非常的重要!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## 我们创建远端仓库的命令",
|
||||||
|
"",
|
||||||
|
"直到现在, 教学都聚焦于本地仓库的基本操作. 但我们现在需要学习远端仓库的操作 -- 我们需要一个配置这种环境的命令, 这个命令就是 `git clone`",
|
||||||
|
"技术上, `git clone` 在真实的环境下, 会在本地创建一个远端仓库的拷贝(比如从github.com). 在我们的教学中使用这个命令会有一些不同 -- 它会在远端创建一个你本地的拷贝. 这和真实命令的意思相反",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"让我们看看远端仓库的样子.",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"就是它了! 现在我们有了一个远端仓库. 除了视觉上的一点变化, 它们真的太像了 -- 在后面的课程中, 你会知道怎样在不同的仓库间分享工作. "
|
||||||
|
],
|
||||||
|
"command": "git clone",
|
||||||
|
"beforeCommand": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"要完成本节, 简单的 `git clone` 下你的仓库. 后续的课程我们会正式的学习"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Remotes",
|
||||||
|
"",
|
||||||
|
"Entfernte Repositorys sind nicht weiter kompliziert. In dieser Welt des Cloud Computings könnte man vielleicht glauben, dass hinter entfernten Git-Repositorys eine Menge Magie steckt, aber es sind einfach nur Kopien eines Repositorys auf einem anderen Rechner. Du kannst mit diesem Rechner typischerweise über das Internet kommunizieren, was es dir ermöglicht Commits hin und her zu schicken.",
|
||||||
|
"",
|
||||||
|
"Nichts desto weniger haben entfernte Repositorys eine Menge toller Eigenschaften:",
|
||||||
|
"",
|
||||||
|
"- Vor allem: sie sind ein super Backup! Lokale Git-Repositorys können deine Arbeitskopie ein jeden beliebigen früheren Zustand versetzen (wie du ja weißt), aber all diese Informationen liegen eben bei dir lokal. Wenn es Kopien von deinem Repository auf anderen Rechnern gibt, kannst du ruhig all deine Daten verlieren und trotzdem genau da weitermachen, wo du aufgehört hast.",
|
||||||
|
"",
|
||||||
|
"- Noch wichtiger: Remotes geben dem Entwickeln eine soziale Komponente! Wenn eine Kopie deines Projekts woanders liegt können deine Freunde sehr einfach etwas zu dem Projekt beitragen (oder sich deine neuesten Änderungen holen).",
|
||||||
|
"",
|
||||||
|
"Websites, die die Aktivitäten um diese entfernten Repositorys darstellen (wie [Github](https://github.com/) oder [Phabricator](http://phabricator.org/)) erfreuen sich zunehmender Beliebtheit, aber entfernte Repositorys sind _immer_ das Rückgrat für diese Werkzeuge. Deshalb ist es wichtig, sie zu verstehen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Der Befehl um ein Remote zu erstellen",
|
||||||
|
"",
|
||||||
|
"Bis jetzt hat sich Learn Git Branching darauf konzentriert, die Grundlagen der _lokalen_ Arbeit mit Repositorys zu vermitteln (Branche anlegen, zusammenführen, Rebasen etc). Jetzt wollen wir allerdings lernen mit entfernten Repositorys zu arbeiten und brauchen für die Level eine entsprechende Umgebung. Die schaffen wir mit `git clone`.",
|
||||||
|
"",
|
||||||
|
"In der Realität ist `git clone` eigentlich der Befehl, mit dem du eine _lokale_ Kopie eines _entfernten_ Repositorys erstellst (das zum Beispiel auf Github liegt). Wir benutzen diesen Befehl in Learn Git Branching allerdings ein wenig anders -- hier macht `git clone` tatsächlich eine Kopie von deinem lokalen Repository auf einem \"entfernten Server\". Klar, das ist eigentlich genau das Gegenteil von dem was der echte Befehl macht, aber es hilft den Zusammenhang zwischen Cloning und der Arbeit mit entfernten Repositorys herzustellen, also machen wir's einfach so.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Fangen wir langsam an und schauen nur wie ein entferntes Repository in unserer Darstellung aussieht.",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Da ist es! Jetzt haben wir ein entferntes Repository unseres Projektes. Es sieht so aus wie das lokale, nur mit ein paar Änderungen in der Darstellung -- in späteren Leveln wirst du sehen, wie man Änderungen zwischen den Repositorys austauschen kann."
|
||||||
|
],
|
||||||
|
"command": "git clone",
|
||||||
|
"beforeCommand": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level abzuschließen führ einfach `git clone` auf deinem bestehenden Repository aus. Alles weitere kommt in den nächsten Leveln."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git clone;git fakeTeamwork 2;git commit ;git pull",
|
"solutionCommand": "git clone;git fakeTeamwork 2;git commit ;git pull",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Faking Teamwork"
|
"en_US": "Faking Teamwork",
|
||||||
|
"de_DE": "Teamarbeit simulieren",
|
||||||
|
"zh_CN": "Faking Teamwork"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "remember you can specify the number of commits to fake"
|
"en_US": "remember you can specify the number of commits to fake",
|
||||||
|
"de_DE": "Nicht vergessen, du kannst angeben wieviele Commits simuliert werden sollen.",
|
||||||
|
"zh_CN": "记住为fake指定数量"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -62,6 +66,114 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## 仿真协同",
|
||||||
|
"",
|
||||||
|
"这里有一件棘手的事 -- 接下来的课程中, 我们需要教你如果从远端拉取变更",
|
||||||
|
"",
|
||||||
|
"这意味着,我们需要假装你的同事、朋友、合作伙伴已经将远端更新到最新了,这些变更有时是一个特别的分支或者确定数目的提交. ",
|
||||||
|
"",
|
||||||
|
"为了做到这点, 我们引入一个自造命令`git fakeTeamwork`. 它是自解释的, 先看演示.."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"`fakeTeamwork` 默认行为就是在在远端master做一个提交."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"成了-- 远端更新了一个新提交. 我们还没有下载它, 因为我们还没有使用`git fetch`."
|
||||||
|
],
|
||||||
|
"command": "git fakeTeamwork",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"你可以指定提交的数量, 只需要在命令后接一个数字!"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"通过一个命令,我们就模拟了队友push 3 个提交到远端的foo分支. "
|
||||||
|
],
|
||||||
|
"command": "git fakeTeamwork foo 3",
|
||||||
|
"beforeCommand": "git branch foo; git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"接下来的学习会相当的困难,所以在本节我们会询问你很多问题. ",
|
||||||
|
"",
|
||||||
|
"继续前进 -- 克隆一个远端,再提交一些修改,在你自己的分支上也做一些提交,再pull一下远端. 这看起来这包含了好几节的课程. "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Zusammenarbeit simulieren",
|
||||||
|
"",
|
||||||
|
"Hier ist das Problem -- für einige der folgenden Level müssen wir lernen, wie man Änderungen vom entfernten Server holt.",
|
||||||
|
"",
|
||||||
|
"Das heißt wir müssen im Grunde \"so tun\" also ob der Server von einem Kollegen / Freund / Mitarbeiter aktualisiert worden wäre, manchmal ein bestimmter Branch oder eine bestimmte Anzahl von Commits.",
|
||||||
|
"",
|
||||||
|
"Um das zu tun führen wir den passend benannten Befehl `git fakeTeamwork` ein! Er ist ziemlich selbsterklärend, schauen wir uns ihn an ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Das normale Verhalten von `fakeTeamwork` ist es, einen Commit auf den entfernten `master` zu machen."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Da haben wir's -- der Server ist mit einem neuen Commit aktualisiert worden und wir haben ihn noch nicht lokal, weil wir nicht `git fetch` oder `git pull` ausgeführt haben."
|
||||||
|
],
|
||||||
|
"command": "git fakeTeamwork",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Du kannst auch angeben wieviele Commits oder auf welchem Branch sie gemacht werden sollen, indem du das an den Befehl anhängst."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Mit einem Befehlt haben wir simuliert, dass ein Kollege drei Commits auf den Branch `foo` gepackt hat."
|
||||||
|
],
|
||||||
|
"command": "git fakeTeamwork foo 3",
|
||||||
|
"beforeCommand": "git branch foo; git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Die kommenden Level werden recht anspruchsvoll, daher verlangen wir auch in diesem Level schon etwas mehr.",
|
||||||
|
"",
|
||||||
|
"Leg los und erstelle ein Remote (mit `git clone`), simuliere ein paar Änderungen auf dem Server, committe lokal und dann zieh dir die Änderungen vom Server. Das ist wie mehrere Level in einem!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git fetch",
|
"solutionCommand": "git fetch",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C3\",\"id\":\"bugFix\"},\"o/master\":{\"target\":\"C2\",\"id\":\"o/master\"},\"o/bugFix\":{\"target\":\"C3\",\"id\":\"o/bugFix\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"bugFix\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C5\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C7\",\"id\":\"bugFix\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C2\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C3\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"bugFix\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C3\",\"id\":\"bugFix\"},\"o/master\":{\"target\":\"C2\",\"id\":\"o/master\"},\"o/bugFix\":{\"target\":\"C3\",\"id\":\"o/bugFix\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"bugFix\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C5\",\"id\":\"master\"},\"bugFix\":{\"target\":\"C7\",\"id\":\"bugFix\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C2\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C4\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C3\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"bugFix\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Git Fetchin'"
|
"en_US": "Git Fetchin'",
|
||||||
|
"de_DE": "Git Fetch",
|
||||||
|
"zh_CN": "Git Fetchin'"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "just run git fetch!"
|
"en_US": "just run git fetch!",
|
||||||
|
"de_DE": "Einfach git fetch ausführen!",
|
||||||
|
"zh_CN": "just run git fetch!"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -17,7 +21,7 @@ exports.level = {
|
||||||
"markdowns": [
|
"markdowns": [
|
||||||
"## Git Fetch",
|
"## Git Fetch",
|
||||||
"",
|
"",
|
||||||
"Working with git remotes really just boils down to transferring data _to_ and _from_ other repositories. As long as we can send commits back and forth, we can share any type of update that is tracked by git (and thus share work, new files, new ideas, love letters, etc etc).",
|
"Working with git remotes really just boils down to transferring data _to_ and _from_ other repositories. As long as we can send commits back and forth, we can share any type of update that is tracked by git (and thus share work, new files, new ideas, love letters, etc.).",
|
||||||
"",
|
"",
|
||||||
"In this lesson we will learn how to fetch data _from_ a remote repository -- the command for this is conveniently named `git fetch`.",
|
"In this lesson we will learn how to fetch data _from_ a remote repository -- the command for this is conveniently named `git fetch`.",
|
||||||
"",
|
"",
|
||||||
|
@ -49,9 +53,9 @@ exports.level = {
|
||||||
"* downloads the commits that the remote has but are missing from our local repository, and...",
|
"* downloads the commits that the remote has but are missing from our local repository, and...",
|
||||||
"* updates where our remote branches point (for instance, `o/master`)",
|
"* updates where our remote branches point (for instance, `o/master`)",
|
||||||
"",
|
"",
|
||||||
"`git fetch` essentially it brings our _local_ representation of the remote repository into synchronization with what the _actual_ remote repository looks like (right now).",
|
"`git fetch` essentially brings our _local_ representation of the remote repository into synchronization with what the _actual_ remote repository looks like (right now).",
|
||||||
"",
|
"",
|
||||||
"If you remember from the previous lesson, we said that remote branches reflect the state of the remote repositories _since_ you last talked to those remotes. `git fetch` is the way you talk to these remotes! Hopefully the connection between remote branches and `git fetch` is apparent now",
|
"If you remember from the previous lesson, we said that remote branches reflect the state of the remote repositories _since_ you last talked to those remotes. `git fetch` is the way you talk to these remotes! Hopefully the connection between remote branches and `git fetch` is apparent now.",
|
||||||
"",
|
"",
|
||||||
"`git fetch` usually talks to the remote repository through the Internet (via a protocol like `http://` or `git://`).",
|
"`git fetch` usually talks to the remote repository through the Internet (via a protocol like `http://` or `git://`).",
|
||||||
""
|
""
|
||||||
|
@ -81,6 +85,150 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Fetch",
|
||||||
|
"",
|
||||||
|
"git remote可以归结为向其它仓库推送/拉取数据. 只要我们能回溯或前推提交, 我们就可以分享任何类型的被git跟踪的更新(工作, 新想法, 情书等等)",
|
||||||
|
"",
|
||||||
|
"本节课我们将学习 如何从远端仓库获取数据 -- 这个命令叫` git fetch`",
|
||||||
|
"",
|
||||||
|
"你会注意到当我们更新远端的仓库时, 我们的远端分支也会更新 并映射到最新的远端仓库."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"在解释`git fetch`前, 我们看看实例. 这里我们有一个包含了两个新提交的远端仓库, 这两新提交不存在于本地"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"就是这样了! `C2`,`C3`被下载到了本地仓库, 同时`o/master`被更新并映射到了这一变更 "
|
||||||
|
],
|
||||||
|
"command": "git fetch",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### What fetch does",
|
||||||
|
"",
|
||||||
|
"`git fetch` 完成了两步:",
|
||||||
|
"",
|
||||||
|
"* 下载本地仓库未包含的提交对象",
|
||||||
|
"* 更新我们的远端分支点(如, `o/master`)",
|
||||||
|
"",
|
||||||
|
"`git fetch` 实际上将本地对远端的映射 做了同步更新",
|
||||||
|
"",
|
||||||
|
"如果你还记得之前的课程, 我们说过远端分支映射了远端仓库的状态(你最后与远端通信的那一刻), `git fetch` 是你与远端交流的方式!",
|
||||||
|
"",
|
||||||
|
"`git fetch` 通常通过互联网(像 `http://` or `git://`) 与远端仓库通信.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### fetch 不能做的事",
|
||||||
|
"",
|
||||||
|
"`git fetch`, 不能改变你的本地状态. 你不会更新你的`master` 或者 任何与文件系统相关的东西.",
|
||||||
|
"",
|
||||||
|
"所以, 你可以将`git fetch`的执行 视为下载"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"要完成本节, 只需用`git fetch`下载所有的提交! "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Fetch",
|
||||||
|
"",
|
||||||
|
"In Git mit entfernten Repositorys zu arbeiten lässt sich wirklich auf das Hin- und Zurückübertragen von Daten reduzieren. Solange wir Commits hin und her schicken können, können wir jede Art Update teilen, das von Git getrackt wird (und somit Arbeit, neue Dateien, neue Ideen, Liebesbriefe etc. teilen).",
|
||||||
|
"",
|
||||||
|
"In diesem Level werden wir lernen, wie man Daten _von_ einem entfernten Repository holt -- der entsprechende Befehl heißt praktischerweise `git fetch`.",
|
||||||
|
"",
|
||||||
|
"Dir wird auffallen, dass mit der Aktualisierung unserer Darstellung des entfernten Repositorys die _Remote_ Branches auf den neuesten Stand gebracht werden. Das passt zum vorherigen Level über Remote Branches."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Bevor wir uns die Einzelheiten von `git fetch` ansehen wollen wir es mal in Aktion sehen. Wir haben hier ein entferntes Repository, das zwei Commits hat die in unserem lokalen Repository fehlen."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Das war's! Die Commits `C2` und `C3` wurden zu unserem Repository heruntergeladen und unser Remote Branch `o/master` wurde aktualisiert."
|
||||||
|
],
|
||||||
|
"command": "git fetch",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Was Fetch tut",
|
||||||
|
"",
|
||||||
|
"`git fetch` führt genau zwei Schritte aus:",
|
||||||
|
"",
|
||||||
|
"* Es lädt die Commits herunter, die im lokalen Repository fehlen, und ...",
|
||||||
|
"* aktualisiert die Remote Branches wo nötig (zum Beispiel, `o/master`).",
|
||||||
|
"",
|
||||||
|
"`git fetch` synchronisiert im Prinzip unsere _lokale_ Abbildung des entfernten Repositorys mit dem wie das entfernte Repository _tatsächlich_ aussieht (in diesem Moment).",
|
||||||
|
"",
|
||||||
|
"Wie du dich vielleicht erinnerst, haben wir im letzten Level gesagt, dass die Remote Branches den Zustand der Branches auf dem entfernten Repository darstellen _seit_ du das letzte Mal dieses Repository angesprochen hast. `git fetch` ist die Methode mit der du das Repository ansprichst! Der Zusammenhang zwischen Remote Branches und `git fetch` ist damit hoffentlich klar.",
|
||||||
|
"",
|
||||||
|
"`git fetch` kommuniziert mit dem entfernten Repository in der Regel über das Internet (über ein Protokoll wie `http://` oder `git://`).",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Was Fetch nicht tut",
|
||||||
|
"",
|
||||||
|
"`git fetch` ändert allerdings überhaupt nichts an _deinen_ lokalen Branches. Es aktualisiert nicht deinen `master` oder ändert irgendetwas an deinem Checkout.",
|
||||||
|
"",
|
||||||
|
"Das ist wichtig zu wissen, denn eine Menge Entwickler glauben, wenn sie `git fetch` ausführen würden ihre lokalen Branches auf den Stand des entfernten Repositorys gebracht. Es lädt zwar alle Daten herunter, damit man diese Aktualisierung durchführen kann, aber es ändert _nichts_ an deinen lokalen Branches. Wir werden in späteren Level Befehle genau dafür kennenlernen. :D",
|
||||||
|
"",
|
||||||
|
"Am Ende des Tages kannst du dir `git fetch` also als den Donwload-Schritt vorstellen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level zu schaffen musst du einfach nur `git fetch` ausführen, um alle Commits herunterzuladen!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git fetch origin master~1:foo;git fetch origin foo:master;git checkout foo;git merge master",
|
"solutionCommand": "git fetch origin master~1:foo;git fetch origin foo:master;git checkout foo;git merge master",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"foo\":{\"target\":\"C1\",\"id\":\"foo\",\"remoteTrackingBranchID\":\"o/foo\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/foo\":{\"target\":\"C1\",\"id\":\"o/foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"C1\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C4\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"foo\":{\"target\":\"C6\",\"id\":\"foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C1\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"}},\"HEAD\":{\"target\":\"foo\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"foo\":{\"target\":\"C1\",\"id\":\"foo\",\"remoteTrackingBranchID\":\"o/foo\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/foo\":{\"target\":\"C1\",\"id\":\"o/foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"C1\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C4\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"foo\":{\"target\":\"C6\",\"id\":\"foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C2\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C1\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"}},\"HEAD\":{\"target\":\"foo\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Fetch arguments"
|
"en_US": "Fetch arguments",
|
||||||
|
"zh_CN": "Fetch arguments",
|
||||||
|
"de_DE": "Optionen für Fetch"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Pay attention how the commit ids may have swapped! You can read slides again with \"help level\""
|
"en_US": "Pay attention how the commit ids may have swapped! You can read slides again with \"help level\"",
|
||||||
|
"zh_CN": "注意下提交对象的id是如何交换的! 你可以通过`help level`再次切到幻灯片!",
|
||||||
|
"de_DE": "Beachte wie die Commit IDs getauscht wurden! Du kannst den Einführungsdialog mit \"help level\" erneut anzeigen"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -37,7 +41,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"Git will go to the `foo` branch on the remote, grab all the commits that aren't present locally, and then plop them down onto the `o/foo` branch locally.",
|
"Git will go to the `foo` branch on the remote, grab all the commits that aren't present locally, and then plop them down onto the `o/foo` branch locally.",
|
||||||
"",
|
"",
|
||||||
"Let's see this in action (just as a refresher)"
|
"Let's see this in action (just as a refresher)."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -75,7 +79,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"Here is the only catch though -- `<source>` is now a place on the *remote* and `<destination>` is a *local* place to put those commits. It's the exact opposite of git push, and that makes sense since we are transferring data in the opposite direction!",
|
"Here is the only catch though -- `<source>` is now a place on the *remote* and `<destination>` is a *local* place to put those commits. It's the exact opposite of git push, and that makes sense since we are transferring data in the opposite direction!",
|
||||||
"",
|
"",
|
||||||
"That being said, developers rarely do this in practice. I'm introducing it mainly as a way to conceptualize how `fetch` and `push` are quite similar, just in opposite directions"
|
"That being said, developers rarely do this in practice. I'm introducing it mainly as a way to conceptualize how `fetch` and `push` are quite similar, just in opposite directions."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -86,7 +90,7 @@ exports.level = {
|
||||||
"Let's see this craziness in action:"
|
"Let's see this craziness in action:"
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"Wow! See, git resolved `foo~1` as a place on the origin and then downloaded those commits to `bar` (which was a local branch). Notice how `foo` and `o/foo` were not updated since we specified a destination"
|
"Wow! See, git resolved `foo~1` as a place on the origin and then downloaded those commits to `bar` (which was a local branch). Notice how `foo` and `o/foo` were not updated since we specified a destination."
|
||||||
],
|
],
|
||||||
"command": "git fetch origin foo~1:bar",
|
"command": "git fetch origin foo~1:bar",
|
||||||
"beforeCommand": "git branch foo; git clone; git branch bar; git fakeTeamwork foo 2"
|
"beforeCommand": "git branch foo; git clone; git branch bar; git fakeTeamwork foo 2"
|
||||||
|
@ -96,10 +100,10 @@ exports.level = {
|
||||||
"type": "GitDemonstrationView",
|
"type": "GitDemonstrationView",
|
||||||
"options": {
|
"options": {
|
||||||
"beforeMarkdowns": [
|
"beforeMarkdowns": [
|
||||||
"What if the destination doesnt exist before I run the command? Lets see the last slide but without `bar` existing beforehand"
|
"What if the destination doesn't exist before I run the command? Let's see the last slide but without `bar` existing beforehand."
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"See, it's JUST like git push. Git made the destination locally before fetching, just like git will make the destination on remote before pushing (if it doesn't exist)"
|
"See, it's JUST like git push. Git made the destination locally before fetching, just like git will make the destination on remote before pushing (if it doesn't exist)."
|
||||||
],
|
],
|
||||||
"command": "git fetch origin foo~1:bar",
|
"command": "git fetch origin foo~1:bar",
|
||||||
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo 2"
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo 2"
|
||||||
|
@ -114,7 +118,7 @@ exports.level = {
|
||||||
"If `git fetch` receives no arguments, it just downloads all the commits from the remote onto all the remote branches..."
|
"If `git fetch` receives no arguments, it just downloads all the commits from the remote onto all the remote branches..."
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"Pretty simple, but worth going over just once"
|
"Pretty simple, but worth going over just once."
|
||||||
],
|
],
|
||||||
"command": "git fetch",
|
"command": "git fetch",
|
||||||
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo; git fakeTeamwork master"
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo; git fakeTeamwork master"
|
||||||
|
@ -131,6 +135,253 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git fetch arguments",
|
||||||
|
"",
|
||||||
|
"我们刚学习了git push的参数, 特别是`<place>`参数, 更特别的冒号分隔(`<source>:<destination>`). 这写参数可以用于`git fetch`吗?",
|
||||||
|
"",
|
||||||
|
"你猜中了! git fetch的参数和git push相当相似. 都是相同的概念, 但是相反相反(因为现在你是下载 而非上传) ",
|
||||||
|
"",
|
||||||
|
"我们过一个概念.."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### `<place>` 参数",
|
||||||
|
"",
|
||||||
|
"你可以像如下命令这样为git fetch设置<place>",
|
||||||
|
"",
|
||||||
|
"`git fetch origin foo`",
|
||||||
|
"",
|
||||||
|
"Git 会来到远端的`foo`分支, 然后抓取所有不在本地的新提交, 放到本地的分支`o/foo`",
|
||||||
|
"",
|
||||||
|
"我们看看这个动作(这像是更新器) "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"通过指定place..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"我们只下载更新了o/foo"
|
||||||
|
],
|
||||||
|
"command": "git fetch origin foo",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"你可以想知道 -- 为何git 会将新提交压入到o/foo 而不是 压入到我本地的foo. 我想 <place>参数就是同时存在于本地和远端 的 <place> ",
|
||||||
|
"",
|
||||||
|
"好吧, 本例中git 有个特殊例外, 因为你可能位于foo 分支, 你也不想弄乱它. 这得联系之前的课程 -- 它不会更新你的本地工作, 它只是下载提交(这样, 稍后你可以检查 或者 合并之). ",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"\"Well in that case, what happens if I explicitly define both the source and destination with `<source>:<destination>`?\"",
|
||||||
|
"如果我们设定了 `<source>:<destination>`会发生什么呢?",
|
||||||
|
"",
|
||||||
|
"如果你觉得直接更新本地分支很爽, 那你就用冒号refspec吧. 不过, 你不能在检出的分支上干这个事.",
|
||||||
|
"",
|
||||||
|
"这里只有一个特点 -- `source` 是远端的位置, 而`<destination>`是要放置提交的本地位置, 这真是有趣 -- 这也是传送数据的对立方向! ",
|
||||||
|
"",
|
||||||
|
"话虽如此, 开发者很少这么做. 我已经介绍了, 概念上fetch/push很相似, 只是它们方向相反. "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"我们看看更疯狂的例子:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"哇! 看见了吧, git 将`foo~1` 解析成一个origin的位置, 然后下载到了本地`bar`. 注意foo 和 o/foo都没有得到更新 (因为我们指定了destination)."
|
||||||
|
],
|
||||||
|
"command": "git fetch origin foo~1:bar",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git branch bar; git fakeTeamwork foo 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"如果 destination 不存在呢? 我们看看上个幻灯片(不含bar)! "
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"看见了吧, 它就像是git push. Git会自己确立本地destination, 就像是git在push时, 会自己确立destination(如果它不存在的话)"
|
||||||
|
],
|
||||||
|
"command": "git fetch origin foo~1",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"没有参数呢?",
|
||||||
|
"",
|
||||||
|
"如果 `git fetch` 没有参数, 它会下载所有远端分支.."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"相当简单, 但是值得一次更新!"
|
||||||
|
],
|
||||||
|
"command": "git fetch",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo; git fakeTeamwork master"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"好, 说得太多了! 要完成本节, 抓取可视窗口指定的提交, 使用这些魔幻的命令吧.",
|
||||||
|
"",
|
||||||
|
"使用fetch时, 你必须指定source/destination. 注意一下可视窗口, 因为提交对象的id可以会被切换哦!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Fetch Optionen",
|
||||||
|
"",
|
||||||
|
"Nun haben wir also alles über `git push` Optionen gelernt, diesen coolen `<Ort>`-Parameter, and sogar über mit Doppelpunkt getrennte Ref-Spezifikationen (`<Quelle>:<Ziel>`). Können wir all dieses neu erworbene Wissen auch auf `git fetch` anwenden?",
|
||||||
|
"",
|
||||||
|
"Jede Wette! Die Optionen für `git fetch` sind wirklicht *sehr, sehr* ähnlich denen von `git push`. Es sind dieselben Verfahren, nur in die andere Richtung angewendet (da man bei `fetch` herunterlädt anstatt hochzuladen).",
|
||||||
|
"",
|
||||||
|
"Gehen wir die verschiedenen Verfahrensweise mal eine nach der anderen durch ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Der Parameter `<Ort>`",
|
||||||
|
"",
|
||||||
|
"Wenn du, wie folgt, einen \"Ort\" bei `git fetch` angibst:",
|
||||||
|
"",
|
||||||
|
"`git fetch origin foo`",
|
||||||
|
"",
|
||||||
|
"wird Git zum Branch `foo` auf dem Remote gehen, dort alle Änderungen holen, die es lokal noch nicht gibt, und sie an den lokalen Branch `o/foo` anhängen.",
|
||||||
|
"",
|
||||||
|
"Schauen wir uns das mal live an (nur zur Wiederholung)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Durch Angabe eines Ortes ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"... laden wir die fehlenden Commits von `foo` und packen sie auf `o/foo` drauf."
|
||||||
|
],
|
||||||
|
"command": "git fetch origin foo",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Du wunderst dich vielleicht warum Git diese Commits auf den `o/foo` Branch gepacht hat, anstatt einfach direkt auf den lokalen Branch `foo`? Zeigt der Parameter `<Ort>` nicht einen Ort an, der sowohl lokal als auch entfernt existiert?",
|
||||||
|
"",
|
||||||
|
"Nun ja, Git geht diesen Schritt weil du auf `foo` ja noch Commits haben könntest, die nicht auf dem Server sind, und da will es nichts durcheinander bringen. Ähnlich wie beim früheren Level zu `git fetch` -- es aktualisiert nicht deine lokalen Arbeits-Branches, es lädt die Commits nur in die `o` (bzw. `origin`) Branches, damit du sie dir in Ruhe anschauen und integrieren kannst.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Wenn das so ist, was passiert dann wenn ich explizit Quelle und Ziel im Ort angebe?",
|
||||||
|
"",
|
||||||
|
"Wenn du Commits wirklich per `fetch` *direkt* auf einen lokalen Branch holen willst, dann, ja, kannst du das mit einer Ref-Spezifikation erreichen. Das funktioniert nicht mit deinem gerade ausgecheckten Branch, aber davon abgesehen lässt Git es zu.",
|
||||||
|
"",
|
||||||
|
"Nur ein Haken -- `<Quelle>` bezeichnet jetzt einen Ort auf dem *entfernten* Server und `<Ziel>` ist ein *lokaler* Ort, wo die Commits hin sollen. Es ist genau umgekehrt wie bei `git push` und das ist logisch, denn wir übertragen die Daten ja auch in die umgekehrte Richtung!",
|
||||||
|
"",
|
||||||
|
"Davon abgesehen benutzt man das in der Praxis kaum. Ich zeige das vor allem um zu verdeutlichen, wie `fetch` und `push` sehr ähnlich sind, nur in entgegengesetzten Richtungen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns den Quatsch mal in Aktion an:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Wow! Siehst du, git löst `foo~1` als Ort auf dem Server `origin` auf und lädt dessen Commits herunter in `bar` hinein. Beachte wie `foo` und `o/foo` *nicht* aktualisiert wurden, da wir ein Ziel angegeben haben."
|
||||||
|
],
|
||||||
|
"command": "git fetch origin foo~1:bar",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git branch bar; git fakeTeamwork foo 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Was ist denn wenn das Ziel nicht existiert, für das ich den Befehl ausführe? Schauen wir uns das letzte Beispiel noch mal an, nur dass `bar` jetzt noch nicht existiert."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Siehst du, es ist *genau* wie `git push`. Git erstellt das Ziel lokal bevor es den `fetch` ausführt, genauso wie Git erst das Ziel auf dem Remote erstellt, befor es pusht (falls das Ziel nicht existiert)."
|
||||||
|
],
|
||||||
|
"command": "git fetch origin foo~1:bar",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Keine Optionen?",
|
||||||
|
"",
|
||||||
|
"Wenn bei `git fetch` keine Optionen angegeben werden, lädt es einfach alle Commits vom Remote auf die lokalen Abbildungen aller Remote Branches ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Ziemlich einfach, aber man sollte es mal gesehen haben."
|
||||||
|
],
|
||||||
|
"command": "git fetch",
|
||||||
|
"beforeCommand": "git branch foo; git clone; git fakeTeamwork foo; git fakeTeamwork master"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Ok, genug gelabert! Um den Level zu schaffen musst du nur die im Zielbild angegebenen Commits per `fetch` holen. Sei kreativ mit den Befehlen!",
|
||||||
|
"",
|
||||||
|
"Du wirst Quelle und Ziel bei beiden `fetch` Befehlen angeben müssen. Schau dir das Zielbild gut an, da die IDs vertauscht sein könnten!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git clone;git fakeTeamwork;git commit;git pull --rebase;git push",
|
"solutionCommand": "git clone;git fakeTeamwork;git commit;git pull --rebase;git push",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Diverged History"
|
"en_US": "Diverged History",
|
||||||
|
"zh_CN": "分散的历史",
|
||||||
|
"de_DE": "Abweichende History"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "check out the ordering from the goal visualization"
|
"en_US": "check out the ordering from the goal visualization",
|
||||||
|
"zh_CN": "检出可视化目标中的顺序",
|
||||||
|
"de_DE": "Beachte die Reihenfolge in der Zieldarstellung"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -55,7 +59,7 @@ exports.level = {
|
||||||
"markdowns": [
|
"markdowns": [
|
||||||
"How do you resolve this situation? It's easy, all you need to do is base your work off of the most recent version of the remote branch.",
|
"How do you resolve this situation? It's easy, all you need to do is base your work off of the most recent version of the remote branch.",
|
||||||
"",
|
"",
|
||||||
"There are a few ways to do this, but the most straightforward is to move your work via rebasing. Let's go ahead and see what that looks like"
|
"There are a few ways to do this, but the most straightforward is to move your work via rebasing. Let's go ahead and see what that looks like."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -105,7 +109,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"Of course -- you already know `git pull` is just shorthand for a fetch and a merge. Conveniently enough, `git pull --rebase` is shorthand for a fetch and a rebase!",
|
"Of course -- you already know `git pull` is just shorthand for a fetch and a merge. Conveniently enough, `git pull --rebase` is shorthand for a fetch and a rebase!",
|
||||||
"",
|
"",
|
||||||
"Let's see these shorthand commands at work"
|
"Let's see these shorthand commands at work."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -116,7 +120,7 @@ exports.level = {
|
||||||
"First with `--rebase`..."
|
"First with `--rebase`..."
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"Same as before! Just a lot shorter"
|
"Same as before! Just a lot shorter."
|
||||||
],
|
],
|
||||||
"command": "git pull --rebase; git push",
|
"command": "git pull --rebase; git push",
|
||||||
"beforeCommand": "git clone; git fakeTeamwork; git commit"
|
"beforeCommand": "git clone; git fakeTeamwork; git commit"
|
||||||
|
@ -151,6 +155,292 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## 分散工作",
|
||||||
|
"",
|
||||||
|
"到现在我们已经知道了如何从其它地方`pull`,以及如果`push`我们自己的提交对象, 看起来真简单, 但是为何人们还会如此困惑呢?",
|
||||||
|
"",
|
||||||
|
"困难来自于远端库历史的分散. 在讨论这个问题的细节前, 我们看一个例子...",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"想象一下你周一克隆了一个仓库, 然后在一个特性分支上工作. 到周五时, 你你准备推送你的特性分支 -- 不行的! 你的同事这周写了一堆代码, 使得你的特性分支过期了. 他们已经将代码分享(合并)到远端仓库了, 所以你的工作就变成了基于仓库老版的代码了.",
|
||||||
|
"",
|
||||||
|
"这种情况下, `git push`就变得模糊了, 如果你执行`git push`, git应该让远端仓库回到星期一那天? 还是直接在新代码的基础上添加你的代码? 或者直接忽略你的提交? ",
|
||||||
|
"",
|
||||||
|
"因为这情况让问题变得模糊(因为历史的分散性)了, git 不会允许你`push`. 你只能先合并远端最新的代码, 然后才能分享你的工作."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": [
|
||||||
|
"你如何解决这事儿呢? 很简单, 你需要做的就是使你的工作基于最新的远端分支.",
|
||||||
|
"",
|
||||||
|
"有好些方法做到这一点呢. 不过最直接的方法就是通过rebase修订你的工作. 我们继续向前,看看这是怎么实现的!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"如果我们在push之前做rebase呢?"
|
||||||
|
],
|
||||||
|
"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": [
|
||||||
|
"First with `--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 的工作流很普遍. 后续课程我们会讲解更复杂的工作流, 不过现在我们先尝试下吧.",
|
||||||
|
"",
|
||||||
|
"要完成本节, 你需要完成以下几步: ",
|
||||||
|
"",
|
||||||
|
"* Clone your repo",
|
||||||
|
"* Fake some teamwork (1 commit)",
|
||||||
|
"* Commit some work yourself (1 commit)",
|
||||||
|
"* Publish your work via *rebasing*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Abweichende Inhalte",
|
||||||
|
"",
|
||||||
|
"Bisher haben wir gesehen wie man per `pull` Commits von Anderen ins lokale Repository holt und die eigenen Änderungen in ein entferntes `push`t. Ist doch ziemlich einfach, wie kann man da durcheinander kommen?",
|
||||||
|
"",
|
||||||
|
"Die Schwierigkeiten entstehen, wenn die Historys der beiden Repositorys *divergieren*, also voneinander abweichen. Bevor wir die Einzelheiten besprechen, schauen wir uns ein Beispiel an ...",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Stell dir vor du holst dir Montags ein Repository per `clone` und fängst an, an einem Feature zu arbeiten. Bis Freitag soll es fertig und veröffentlicht sein -- doch, oh je! Deine Kollegen haben eine Menge Code während der Woche geschrieben, der dein Feature hat veralten lassen (und überflüssig gemacht hat). Sie haben diesen Code außerdem zum entfernten Repository gepusht, und dadurch basiert *deine* harte Arbeit jetzt auf einer *alten* Version des Projektes, die nicht länger relevant ist.",
|
||||||
|
"",
|
||||||
|
"In diesem Fall ist ein `git push` problematisch. Wenn du es ausführst, soll Git das entfernte Repository in den Zustand von Montag zurückversetzen? Soll es versuchen deinen Code auf die aktuelle Version zu packen? Oder soll es deine Änderungen einfach ignorieren, weil sie total veraltet sind?",
|
||||||
|
"",
|
||||||
|
"Da es in dieser Situation so viele Mehrdeutigkeiten gibt (da die Historys divergent sind) erlaubt Git dir nicht, deine Änderungen einfach zu `push`en. Es zwingt dich, zuerst die neuesten Änderungen vom Server zu holen und in deine zu integrieren bevor du deine Arbeit mit anderen teilen kannst."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Bla bla bla. Schauen wir uns das lieber in Aktion an:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Siehst du? Nichts passiert, weil der Befehl fehlschlägt. `git push` schlägt fehl, weil der neueste Commit `C3` auf dem Commit `C1` des Remotes basiert. Der entfernte Server hat mittlerweile jedoch `C2` gepusht bekommen, also lässt Git deinen Push jetzt nicht mehr zu."
|
||||||
|
],
|
||||||
|
"command": "git push",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Wie sollen wir das auflösen? Es ist ganz einfach, du musst deinen Commit nur von der aktuellsten Version des Remotes ableiten.",
|
||||||
|
"",
|
||||||
|
"Es gibt verschiedene Möglichkeiten wie man das erreichen kann, aber die offensichtlichste ist es, deine Commits per Rebase zu verschieben. Schauen wir mal wie das abläuft:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Also wenn wir vor dem Push erst mal einen Rebase mache ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Bämm! Wir haben unsere lokale Abbildung des entfernten Repositorys mit `git fetch` auf den neuesten Stand gebracht, unsere Arbeit auf die neueste Version des Remotes drauf gepackt und dann mit `git push` auf den Server geschoben."
|
||||||
|
],
|
||||||
|
"command": "git fetch; git rebase o/master; git push",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Gibt es noch weitere Möglichkeiten deine Arbeit zu aktualisieren wenn das entfernte Repository neue Commits bekommen hat? Klar! Schauen wir uns dasselbe an, aber diesmal arbeiten wir mit `merge`.",
|
||||||
|
"",
|
||||||
|
"Obwohl `git merge` deine Arbeit nicht verschiebt (und stattdessen einen Merge Commit erzeugt) ist es eine Möglichkeit Git dazu zu bringen, alle Änderungen vom Remote in deine Sachen zu integrieren. Denn durch den Merge wird der Remote Branch zu einem *Vorgänger* deines Branches, was bedeutet dass dein Commit alle Commits des entfernten Branches beinhaltet.",
|
||||||
|
"",
|
||||||
|
"Zur Demonstration ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Wenn wir nun also mergen anstatt einen Rebase zu machen ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Ok. Wir haben die lokale Abbildung des entfernen Repositorys mit `git fetch` aktualisiert, die neuen Änderungen per *Merge* in deine integriert, und letztere dann mit `git push` auf den Server gebracht."
|
||||||
|
],
|
||||||
|
"command": "git fetch; git merge o/master; git push",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Wahnsinn! Kann ich das auch irgendwie machen ohne soviel zu tippen?",
|
||||||
|
"",
|
||||||
|
"Na klar -- du kennst ja schon `git pull` als Zusammenfassung von `fetch` und `merge`. Praktischerweise bringt man es mit der Option `--rebase` dazu, anstatt des Merge einen Rebase zu machen.",
|
||||||
|
"",
|
||||||
|
"Gucken wir uns das mal an."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Zunächst `git pull --rebase` ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Genau wie vorher! Nur viel kürzer."
|
||||||
|
],
|
||||||
|
"command": "git pull --rebase; git push",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Und nun das normale `git pull` ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Und wieder, genau wie zuvor!"
|
||||||
|
],
|
||||||
|
"command": "git pull; git push",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Dieser Ablauf von `fetch`, `rebase` / `merge` und `push` ist sehr verbreitet. In zukünftigen Leveln werden wir uns kompliziertere Varianten dieses Workflows ansehen, aber jetzt probieren wir erst mal diesen aus.",
|
||||||
|
"",
|
||||||
|
"Um diesen Level zu lösen, gehe folgende Schritte durch:",
|
||||||
|
"",
|
||||||
|
"* Clone dein Repository",
|
||||||
|
"* Simuliere einen entfernten Commit mit `git fakeTeamwork`",
|
||||||
|
"* Erzeuge einen lokalen Commit",
|
||||||
|
"* Benutze *Rebase*, um deine Arbeit schließlich pushen zu können"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git checkout master;git pull;git merge side1;git merge side2;git merge side3;git push",
|
"solutionCommand": "git checkout master;git pull;git merge side1;git merge side2;git merge side3;git push",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\",\"localBranchesThatTrackThis\":null},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":[\"master\"]},\"side1\":{\"target\":\"C2\",\"id\":\"side1\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side2\":{\"target\":\"C4\",\"id\":\"side2\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side3\":{\"target\":\"C7\",\"id\":\"side3\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C1\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"side3\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C8\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C8\":{\"parents\":[\"C1\"],\"id\":\"C8\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\",\"localBranchesThatTrackThis\":null},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":[\"master\"]},\"side1\":{\"target\":\"C2\",\"id\":\"side1\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side2\":{\"target\":\"C4\",\"id\":\"side2\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side3\":{\"target\":\"C7\",\"id\":\"side3\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C1\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"side3\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C8\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C8\":{\"parents\":[\"C1\"],\"id\":\"C8\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Merging with remotes"
|
"en_US": "Merging with remotes",
|
||||||
|
"zh_CN": "Merging with remotes",
|
||||||
|
"de_DE": "Änderungen vom Remote zusammenführen"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Pay attention to the goal tree!"
|
"en_US": "Pay attention to the goal tree!",
|
||||||
|
"zh_CN": "注意目标树!",
|
||||||
|
"de_DE": "Beachte den Ziel-Baum!"
|
||||||
},
|
},
|
||||||
"compareOnlyMaster": true,
|
"compareOnlyMaster": true,
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
|
@ -29,7 +33,7 @@ exports.level = {
|
||||||
"type": "ModalAlert",
|
"type": "ModalAlert",
|
||||||
"options": {
|
"options": {
|
||||||
"markdowns": [
|
"markdowns": [
|
||||||
"Theres a lot of debate about the tradeoffs between merging and rebasing in the development community. Here are the general pros / cons of rebasing:",
|
"There's a lot of debate about the tradeoffs between merging and rebasing in the development community. Here are the general pros / cons of rebasing:",
|
||||||
"",
|
"",
|
||||||
"Pros:",
|
"Pros:",
|
||||||
"",
|
"",
|
||||||
|
@ -49,7 +53,97 @@ exports.level = {
|
||||||
"type": "ModalAlert",
|
"type": "ModalAlert",
|
||||||
"options": {
|
"options": {
|
||||||
"markdowns": [
|
"markdowns": [
|
||||||
"For this level, let's try to solve the previous level but with *merging* instead. It may get a bit hairy but it illustrates the point well"
|
"For this level, let's try to solve the previous level but with *merging* instead. It may get a bit hairy but it illustrates the point well."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Warum nicht Merge?",
|
||||||
|
"",
|
||||||
|
"Um neue Dinge auf das Remote zu schieben musst du erst alle Änderungen vom Remote holen und bei dir integrieren. Das bedeutet du kannst den entfernten Branch (z.B. `o/master`) entweder Rebasen *oder* Mergen.",
|
||||||
|
"",
|
||||||
|
"Wenn du also beide Methoden benutzen kannst, warum haben sich die Level bisher auf Rebase konzentriert? Warum mag keiner `merge` wenn es um Remotes geht?",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Es gibt eine Menge Diskussionen unter Entwicklern über die Vor- und Nachteile beim Mergen und Rebasen. Hier ein paar Vor- und Nachteile zum Rebasen:",
|
||||||
|
"",
|
||||||
|
"Vorteile:",
|
||||||
|
"",
|
||||||
|
"* Rebasen macht den Commit-Baum sehr übersichtlich, weil alles linear aufeinander aufbaut",
|
||||||
|
"",
|
||||||
|
"Nachteile:",
|
||||||
|
"",
|
||||||
|
"* Rebasen verändert die History eines Branches.",
|
||||||
|
"",
|
||||||
|
"Zum Beispiel kann durch Rebasen Commit `C1` an Commit `C3` *vorbei* bewegt werden, bzw. eine Kopie von `C1`. Es sieht dann so aus als wären die Änderungen in `C1` nach denen in `C3` gemacht worden, obwohl das nicht stimmt.",
|
||||||
|
"",
|
||||||
|
"Manche Entwickler möchten lieber die History lassen wie sie ist und ziehen daher das Mergen vor. Andere (wie ich) haben lieber einen sauberen Commit-Baum und ziehen Rebase vor. Am Ende ist es eine Geschmacksfrage. :D"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"In diesem Level wollen wir versuchen die Aufgabe vom letzten Level erneut zu lösen, aber diesmal mit einem *Merge*. Das wird vielleicht etwas haariger, stellt aber gut die Implikationen dar."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## 为何不merge?",
|
||||||
|
"",
|
||||||
|
"为了push新变更到远端,你要做的就是合并远端最新变更(使用rebase or merge). ",
|
||||||
|
"",
|
||||||
|
"所以你可以使用任意一种方法, 但为何何本节会聚焦于rebasing呢?为会不喜欢用merge 去合并remote呢?",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"在开发社区,有相当多的关于权衡的讨论。以下是关于rebasing的优点/缺点: ",
|
||||||
|
"",
|
||||||
|
"优点:",
|
||||||
|
"",
|
||||||
|
"* Rebase使你的提交树变得很干净, 所有的提交成了一条线: ",
|
||||||
|
"",
|
||||||
|
"缺点:",
|
||||||
|
"",
|
||||||
|
"* Rebase修改的提交树的父历史",
|
||||||
|
"",
|
||||||
|
"比如, 提交C1 可以被修订到跃过C3. 这看起来C1 是在C3 之后 (而实际上可能在C3之前) ",
|
||||||
|
"",
|
||||||
|
"一些开发者喜欢保留提交历史,更偏爱merging。而其它的人而喜欢拥有更干净的提交树,偏爱rebasing. 这些都依赖于自己的偏爱. :D"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"本节, 我们要解决前面的单元问题,但是要用merging。 这显得有点那个啥的,但这只是为了更好的说明这一点。 "
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git pull",
|
"solutionCommand": "git pull",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\",\"localBranchesThatTrackThis\":null},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":[\"master\"]}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C3\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\",\"localBranchesThatTrackThis\":null},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":[\"master\"]}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C3\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Git Pullin'"
|
"en_US": "Git Pullin'",
|
||||||
|
"zh_CN": "Git Pullin'",
|
||||||
|
"de_DE": "Git Pull"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Just run git pull!"
|
"en_US": "Just run git pull!",
|
||||||
|
"zh_CN": "Just run git pull!",
|
||||||
|
"de_DE": "Führe einfach git pull aus."
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -17,14 +21,14 @@ exports.level = {
|
||||||
"markdowns": [
|
"markdowns": [
|
||||||
"## Git Pull",
|
"## Git Pull",
|
||||||
"",
|
"",
|
||||||
"Now that we've seen how to fetch data from a remote repository with `git fetch`, lets update our work to reflect those changes!",
|
"Now that we've seen how to fetch data from a remote repository with `git fetch`, let's update our work to reflect those changes!",
|
||||||
"",
|
"",
|
||||||
"There are actually many ways to do this -- once you have new commits available locally, you can incorporate them as if they were just normal commits on other branches. This means you could execute commands like:",
|
"There are actually many ways to do this -- once you have new commits available locally, you can incorporate them as if they were just normal commits on other branches. This means you could execute commands like:",
|
||||||
"",
|
"",
|
||||||
"* `git cherry-pick o/master`",
|
"* `git cherry-pick o/master`",
|
||||||
"* `git rebase o/master`",
|
"* `git rebase o/master`",
|
||||||
"* `git merge o/master`",
|
"* `git merge o/master`",
|
||||||
"* etc, etc",
|
"* etc., etc.",
|
||||||
"",
|
"",
|
||||||
"In fact, the workflow of *fetching* remote changes and then *merging* them is so common that git actually make a command that does both at once! That command is `git pull`."
|
"In fact, the workflow of *fetching* remote changes and then *merging* them is so common that git actually make a command that does both at once! That command is `git pull`."
|
||||||
]
|
]
|
||||||
|
@ -67,6 +71,124 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Pull",
|
||||||
|
"",
|
||||||
|
"现在我们已经知道了如何用`git fetch` 获取远端的变化, 现在我们学习如果将这些变化更新到我们的工作.",
|
||||||
|
"",
|
||||||
|
"其实有很多方法的 -- 只要我在本地有新的提交, 你可以像合并其它分支那样合并远端分支. 具体说就是你可以执行以下命令: ",
|
||||||
|
"",
|
||||||
|
"* `git cherry-pick o/master`",
|
||||||
|
"* `git rebase o/master`",
|
||||||
|
"* `git merge o/master`",
|
||||||
|
"* etc, etc",
|
||||||
|
"",
|
||||||
|
"实际上, fetch / merge 变更是这样的普通, 以至于git 提供了一个实际两个功能的命令 -- `git pull`."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"我们先顺序执行`fetch`,`merge` "
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"我们用`fetch`下载了`C3`, 然后通过`git merge o/master`合并了这一提交. 现在我们的`master`分支映射到了远端的新工作"
|
||||||
|
],
|
||||||
|
"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再跟一个merge的缩写! "
|
||||||
|
],
|
||||||
|
"command": "git pull",
|
||||||
|
"beforeCommand": "git clone; git commit; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"稍后我们会扫一下`git pull`的细节(选项和参数), 现在我们先完成作业.",
|
||||||
|
"",
|
||||||
|
"记住, 你可以用fetch/merge 通过本节, 但是这会增加你的命令.:P"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Pull",
|
||||||
|
"",
|
||||||
|
"Jetzt, wo wir wissen wie wir mit `git fetch` Daten von einem entfernten Repository holen können, wollen wir unsere lokalen Daten aktualisieren, damit sie die Änderungen vom Server beinhalten.",
|
||||||
|
"",
|
||||||
|
"Tatsächlich gibt es eine Menge Wege dies zu erreichen -- sobald du die neuen Commits lokal verfügbar hast, kannst du sie integrieren so als wären es Commits von ganz normalen anderen Branches. Du kannst also:",
|
||||||
|
"",
|
||||||
|
"* `git cherry-pick o/master`",
|
||||||
|
"* `git rebase o/master`",
|
||||||
|
"* `git merge o/master`",
|
||||||
|
"* usw. usf. ausfúhren.",
|
||||||
|
"",
|
||||||
|
"Der Ablauf, die Änderungen vom Server zu holen und dann in die eigene Arbeit zu mergen wird so häufig benötigt, dass Git einen Befehl kennt der beides auf einmal erledigt! Das ist `git pull`."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns erst mal ein `fetch` gefolgt von `merge` an:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Bämm -- wir haben `C3` mit `fetch` heruntergeladen und dann in unseren Branch mit `git merge o/master` integriert. Nun bildet unser `master` dieselben Inhalte ab, wie sie auf dem entfernten Server (`origin`) liegen."
|
||||||
|
],
|
||||||
|
"command": "git fetch; git merge o/master",
|
||||||
|
"beforeCommand": "git clone; git commit; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Was passiert wohl, wenn wir stattdessen `git pull` benutzen?"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Dasselbe in Pink. Das sollte recht deutlich machen, dass `git pull` nur eine Abkürzung für `git fetch` gefolgt von einem Merge des gerade aktualisierten Branches ist."
|
||||||
|
],
|
||||||
|
"command": "git pull",
|
||||||
|
"beforeCommand": "git clone; git commit; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Die Feinheiten von `git pull` werden wir uns später ansehen, für's Erste lass es uns in diesem Level ausprobieren.",
|
||||||
|
"",
|
||||||
|
"Vergiss nicht -- du kannst diesen Level auch mit `fetch` und `merge` lösen, aber das kostet dich einen Befehl extra. :P"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git pull origin bar:foo;git pull origin master:side",
|
"solutionCommand": "git pull origin bar:foo;git pull origin master:side",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C4\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/bar\":{\"target\":\"C1\",\"id\":\"o/bar\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C4\":{\"parents\":[\"C1\"],\"id\":\"C4\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"bar\":{\"target\":\"C3\",\"id\":\"bar\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"bar\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C4\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/bar\":{\"target\":\"C1\",\"id\":\"o/bar\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C4\":{\"parents\":[\"C1\"],\"id\":\"C4\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"bar\":{\"target\":\"C3\",\"id\":\"bar\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"}},\"HEAD\":{\"target\":\"bar\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Pull arguments"
|
"en_US": "Pull arguments",
|
||||||
|
"zh_CN": "Pull arguments",
|
||||||
|
"de_DE": "Optionen für Pull"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember that you can create new local branches with fetch/pull arguments"
|
"en_US": "Remember that you can create new local branches with fetch/pull arguments",
|
||||||
|
"zh_CN": "记住, 你可以通过fetch/pull创建本地分支",
|
||||||
|
"de_DE": "Du kannst neue lokale Branches mittels fetch / pull erstellen"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -19,7 +23,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"Now that you know pretty much *everything* there is to know about arguments for `git fetch` and `git push`, there's almost really nothing left to cover for git pull :)",
|
"Now that you know pretty much *everything* there is to know about arguments for `git fetch` and `git push`, there's almost really nothing left to cover for git pull :)",
|
||||||
"",
|
"",
|
||||||
"That's because git pull at the end of the day is *really* just shorthand for a fetch followed by merging in whatever was just fetched. You can think of it as running git fetch with SAME arguments specified and then merging in *where* those commits ended up.",
|
"That's because git pull at the end of the day is *really* just shorthand for a fetch followed by merging in whatever was just fetched. You can think of it as running git fetch with the *same* arguments specified and then merging in *where* those commits ended up.",
|
||||||
"",
|
"",
|
||||||
"This applies even when you use crazy-complicated arguments as well. Let's see some examples:"
|
"This applies even when you use crazy-complicated arguments as well. Let's see some examples:"
|
||||||
]
|
]
|
||||||
|
@ -41,7 +45,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"`git fetch origin bar~1:bugFix; git merge bugFix`",
|
"`git fetch origin bar~1:bugFix; git merge bugFix`",
|
||||||
"",
|
"",
|
||||||
"See? git pull is really just shorthand for fetch + merge, and all git pull cares about is where the commits ended up (the `destination` argument that it figures out during fetch)",
|
"See? git pull is really just shorthand for fetch + merge, and all git pull cares about is where the commits ended up (the `destination` argument that it figures out during fetch).",
|
||||||
"",
|
"",
|
||||||
"Lets see a demo:"
|
"Lets see a demo:"
|
||||||
]
|
]
|
||||||
|
@ -82,6 +86,156 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git pull 参数",
|
||||||
|
"",
|
||||||
|
"现在你知道关于fetch/push几乎所有的东西了, 不过pull也有一个\"nothing\"呢!:)",
|
||||||
|
"",
|
||||||
|
"That's because git pull at the end of the day is *really* just shorthand for a fetch followed by merging in whatever was just fetched. You can think of it as running git fetch with SAME arguments specified and then merging in *where* those commits ended up.",
|
||||||
|
"因为 git pull 就是fetch后跟merge的缩写. 我可以认为执行git fetch 用了相同的参数, 然后再merge 你所fetch的提交(commit)",
|
||||||
|
"",
|
||||||
|
"这可以和其它更复杂的参数一起使用, 看看例子:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Here are some equivalent commands in git:",
|
||||||
|
"以下命令在git中是等价的:",
|
||||||
|
"",
|
||||||
|
"`git pull origin foo` is equal to:",
|
||||||
|
"",
|
||||||
|
"`git fetch origin foo; git merge o/foo`",
|
||||||
|
"",
|
||||||
|
"还有...",
|
||||||
|
"",
|
||||||
|
"`git pull origin bar~1:bugFix` is equal to:",
|
||||||
|
"",
|
||||||
|
"`git fetch origin bar~1:bugFix; git merge bugFix`",
|
||||||
|
"",
|
||||||
|
"看到了? git pull 实际上就是fetch + merge的缩写, git pull 在乎的是提交在哪里结束(也就是git fetch所确定的destination)",
|
||||||
|
"",
|
||||||
|
"Lets see a demo:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"如果我们指定要提取的<place>, 所有的事情都会跟之前一样发生, 除了merge. "
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"看! 通过指定master 我们更新了o/master. 然后我们merge `o/master` 到我们的检出分支(当前检出的任意分支). "
|
||||||
|
],
|
||||||
|
"command": "git pull origin master",
|
||||||
|
"beforeCommand": "git clone; go -b bar; git commit; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"这也适用于source / destination 吗? 当然喽, 看看吧:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
" 哇, 这就一个命令. 我们在本地创建了一个叫foo的分支, 远端的master分支, 被下载到了本地foo分支. 然后再merge到我们的当前分支. 终于完啦!9000!!!"
|
||||||
|
],
|
||||||
|
"command": "git pull origin master:foo",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork; go -b bar; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"好啦, 做作业! 请获取虚拟目标. 你需要下载一些提交,然后创建一些新分支, 再合并这些分支到其它分支, 这花不了几个命令 :P "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Optionen für Git Pull",
|
||||||
|
"",
|
||||||
|
"Da du jetzt so ziemlich *alles* kennst, was es an Optionen für `git fetch` und `git push` gibt, ist kaum noch etwas zu Optionen für `git pull` zu sagen. :)",
|
||||||
|
"",
|
||||||
|
"Das liegt daran, dass `git pull` letztendlich *wirklich* nur eine Abkürzuung für `fetch` gefolgt von einem `merge` von was auch immer gerade heruntergeladen wurde, ist. Denk es dir als ein `git fetch` mit denselben Optionen und einem anschließenden Merge.",
|
||||||
|
"",
|
||||||
|
"Das trifft sogar zu, wenn du völlig abgedrehte Optionen verwendest. Ein paar Beispiele:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Hier sind einige gleichwertige Befehle in Git:",
|
||||||
|
"",
|
||||||
|
"`git pull origin foo` ist dasselbe wie:",
|
||||||
|
"",
|
||||||
|
"`git fetch origin foo; git merge o/foo`",
|
||||||
|
"",
|
||||||
|
"Und ...",
|
||||||
|
"",
|
||||||
|
"`git pull origin bar~1:bugFix` ist dasselbe wie:",
|
||||||
|
"",
|
||||||
|
"`git fetch origin bar~1:bugFix; git merge bugFix`",
|
||||||
|
"",
|
||||||
|
"Siehst du? `git pull` ist wirklich nur eine Abkürzung von `fetch` + `merge` und es interessiert sich nur dafür wo die Commits hin sollen (die \"Ziel\"-Option, die es beim `fetch` auswertet).",
|
||||||
|
"",
|
||||||
|
"Schauen wir uns eine Demonstration an:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Wenn wir den Ort, auf den das `fetch` ausgeführt werden soll, angeben, passiert alles so wie beim `git fetch` aber es wird direkt danach auch ein Merge ausgeführt."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Siehst du? Da wir `master` angegeben haben sind die Commits in `o/master` heruntergeladen worden. Danach wurde `o/master` gemerged, egal was gerade ausgecheckt war."
|
||||||
|
],
|
||||||
|
"command": "git pull origin master",
|
||||||
|
"beforeCommand": "git clone; go -b bar; git commit; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Funktioniert das auch wenn man Quelle und Ziel angibt? Aber sicher! Das sehen wir hier:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Wow, das ist eine Menge in einem einzelnen Befehl. Wir haben lokal einen neuen Branch namens `foo` erstellt, die Commits vom `master` des Servers dorthin heruntergeladen und ihn danach in unseren aktuell ausgecheckten Commit `bar` gemerged."
|
||||||
|
],
|
||||||
|
"command": "git pull origin master:foo",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork; go -b bar; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Ok, um's zu Ende zu bringen versuch das Ziel aus der Zielgrafik zu erreichen. Du wirst einige Commits herunterladen, einige neue Branches anlegen und diese in andere mergen müssen, aber das sollte nicht allzuviele Befehle benötigen. :P"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git clone;git commit;git commit;git push",
|
"solutionCommand": "git clone;git commit;git commit;git push",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Git Pushin'"
|
"en_US": "Git Pushin'",
|
||||||
|
"zh_CN": "Git Pushin'",
|
||||||
|
"de_DE": "Git Push"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember you have to clone before you can push!"
|
"en_US": "Remember you have to clone before you can push!",
|
||||||
|
"zh_CN": "push之前你需要先克隆.",
|
||||||
|
"de_DE": "Denk dran, dass du einen Clone brauchst bevor du Pushen kannst!"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -23,7 +27,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"`git push` is responsible for uploading _your_ changes to a specified remote and updating that remote to incorporate your new commits. Once `git push` completes, all your friends can then download your work from the remote.",
|
"`git push` is responsible for uploading _your_ changes to a specified remote and updating that remote to incorporate your new commits. Once `git push` completes, all your friends can then download your work from the remote.",
|
||||||
"",
|
"",
|
||||||
"You can think of `git push` as a command to \"publish\" your work. It has a bunch of subtleties that we will get into shortly, but let's start with baby steps"
|
"You can think of `git push` as a command to \"publish\" your work. It has a bunch of subtleties that we will get into shortly, but let's start with baby steps."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -49,6 +53,88 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Push",
|
||||||
|
"",
|
||||||
|
"太棒了, 我们已经学习了从远端获取|合并工作到我们的本地工作.但是我们如果分享工作呢?",
|
||||||
|
"",
|
||||||
|
"好吧, 上载工作正好同下载工作相反, 那与`git pull`相反的命令是什么? `git push`! ",
|
||||||
|
"",
|
||||||
|
"`git push` 负责将你的提交上传到远端, 一旦`git push`完成, 你的朋友就可以在远端下载你的工作了! ",
|
||||||
|
"",
|
||||||
|
"你可以将`git push`视为发布你工作的命令. 它有一些特别的地方, 稍后我们会了解到, 我们开始吧."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"这里我们有一个变更, 而远端却没有, 我们先上传吧!"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"到了, 远端收到的了`C2`提交, 远端的`master`分支 也被更新并指到了`C2`,我们的远端代表(o/master)也同样被更新了. 所有的东西都被同步了!"
|
||||||
|
],
|
||||||
|
"command": "git push",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"要完成本节, 需要向远端分享两提交. 戒骄戒躁,课程还会更难哦! "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git Push",
|
||||||
|
"",
|
||||||
|
"Nun hab ich also Änderungen vom entfernten Server geholt und in meine lokale Arbeit integriert. Das ist schön und gut ... aber wie teile ich _meine_ Wahnsinns-Entwicklungen mit allen anderen?",
|
||||||
|
"",
|
||||||
|
"Naja, das Hochladen von Zeug ist das Gegenteil zum Herunterladen von Zeug. Und was ist das Gegenteil von `git pull`? Genau, `git push`!",
|
||||||
|
"",
|
||||||
|
"`git push` ist dafür verantwortlich _deine_ Änderungen zu einem bestimmten entfernten Server hochzuladen und dort zu integrieren. Sobald das `git push` durch ist, können alle deine Freunde diese Änderungen zu sich herunterladen.",
|
||||||
|
"",
|
||||||
|
"Du kannst dir `git push` als einen Befehl zum \"Veröffentlichen\" deiner Arbeit vorstellen. Es gibt da noch ein paar Feinheiten, aber lass uns mal mit kleinen Schritten anfangen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Hier haben wir ein paar Änderungen, die auf dem Remote noch fehlen. Und hoch damit!"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Na bitte -- das Remote hat den Commit `C2` bekommen, der `master` auf dem Remote ist entsprechend aktualisiert worden und unsere *eigene* Abbildung des `master` auf dem Remote namens `o/master` wurde auch aktualisiert. Alles im Lot!"
|
||||||
|
],
|
||||||
|
"command": "git push",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level zu schaffen musst du einfach nur zwei neue Commits auf das Remote bringen. Aber stell dich schon mal darauf ein, dass die nächsten Level anspruchsvoller werden!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,13 @@ exports.level = {
|
||||||
"git checkout": true
|
"git checkout": true
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Git push arguments"
|
"en_US": "Git push arguments",
|
||||||
|
"zh_CN": "Git push 参数",
|
||||||
|
"de_DE": "Optionen für Git Push"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "You can always look at the last slide of the dialog with \"objective\""
|
"en_US": "You can always look at the last slide of the dialog with \"objective\"",
|
||||||
|
"de_DE": "Du kannst dir die Zielsetzung des Levels immer wieder mit \"objective\" anzeigen lassen"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -40,7 +43,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"translates to this in English:",
|
"translates to this in English:",
|
||||||
"",
|
"",
|
||||||
"*Go to the branch named \"master\" in my repository, grab all the commits, and then go to the branch \"master\" on the remote named \"origin.\" Place whatever commits are missing on that branch and then tell me when you're done*",
|
"*Go to the branch named \"master\" in my repository, grab all the commits, and then go to the branch \"master\" on the remote named \"origin.\" Place whatever commits are missing on that branch and then tell me when you're done.*",
|
||||||
"",
|
"",
|
||||||
"By specifying `master` as the \"place\" argument, we told git where the commits will *come from* and where the commits *will go*. It's essentially the \"place\" or \"location\" to synchronize between the two repositories.",
|
"By specifying `master` as the \"place\" argument, we told git where the commits will *come from* and where the commits *will go*. It's essentially the \"place\" or \"location\" to synchronize between the two repositories.",
|
||||||
"",
|
"",
|
||||||
|
@ -52,10 +55,10 @@ exports.level = {
|
||||||
"type": "GitDemonstrationView",
|
"type": "GitDemonstrationView",
|
||||||
"options": {
|
"options": {
|
||||||
"beforeMarkdowns": [
|
"beforeMarkdowns": [
|
||||||
"Let's see an example of specifying the arguments. Note the location where we are checked out in this example"
|
"Let's see an example of specifying the arguments. Note the location where we are checked out in this example."
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"There we go! `master` got updated on the remote since we specified those arguments"
|
"There we go! `master` got updated on the remote since we specified those arguments."
|
||||||
],
|
],
|
||||||
"command": "git checkout C0; git push origin master",
|
"command": "git checkout C0; git push origin master",
|
||||||
"beforeCommand": "git clone; git commit"
|
"beforeCommand": "git clone; git commit"
|
||||||
|
@ -68,7 +71,7 @@ exports.level = {
|
||||||
"What if we hadn't specified the arguments? What would happen?"
|
"What if we hadn't specified the arguments? What would happen?"
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"The command fails (as you can see), since `HEAD` is not checked out on a remote-tracking branch"
|
"The command fails (as you can see), since `HEAD` is not checked out on a remote-tracking branch."
|
||||||
],
|
],
|
||||||
"command": "git checkout C0; git push",
|
"command": "git checkout C0; git push",
|
||||||
"beforeCommand": "git clone; git commit"
|
"beforeCommand": "git clone; git commit"
|
||||||
|
@ -83,6 +86,150 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Push 参数",
|
||||||
|
"",
|
||||||
|
"Great! Now that you know about remote tracking branches we can start to uncover some of mystery behind how git push, fetch, and pull work. We're going to tackle one command at a time but the concepts between them are very similar.",
|
||||||
|
"好! 既然你知道了远端跟踪分支, 我们可以开始揭开隐藏在git push/pull/fetch背后的秘密. ",
|
||||||
|
"",
|
||||||
|
"首先看看`git push`, 在远端跟踪分支中, 你学到了git 会找出要push的目的地(通过查看检出的分支, 及分支关联到的跟踪分支). 这是无参数的行为, 不过我们也可以为push指定参数:",
|
||||||
|
"",
|
||||||
|
"`git push <remote> <place>`",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"What is a `<place>` parameter you say? We'll dive into the specifics soon, but first an example. Issuing the command:",
|
||||||
|
"`<place>` 参数意味什么呢? 我们会深入其中的细节, 先看看例子, 这个命令是:",
|
||||||
|
"",
|
||||||
|
"`git push origin master`",
|
||||||
|
"",
|
||||||
|
"* 切到master分支, 然后抓取所有的提交, 再将新提交推送到远端的master分支!",
|
||||||
|
"",
|
||||||
|
"通过指定`master`为<place>参数, 我们告诉git 提交来自于master, 要推送到远端的master. 这种使用方式基本上用于同步两仓库",
|
||||||
|
"",
|
||||||
|
"谨记, 因为我们通过指定参数告诉了git 所有的事, git 就忽略了我们所检出的分支(转而直接使用参数指定的分支作为source/destination)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"我们看看指定参数的例子. 注意下我们当前检出的位置."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"好了! 通过指定参数, 远端的`master` 得到了更新"
|
||||||
|
],
|
||||||
|
"command": "git checkout C0; git push origin master",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"不指定参数会发生什么呢?"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"命令失败了! 因为我们所check out 的HEAD没有跟踪分支. "
|
||||||
|
],
|
||||||
|
"command": "git checkout C0; git push",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"本节, 我们要更新远端的`foo`和`master`, 在本节中`git checkout` 是被禁用的!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Push-Optionen",
|
||||||
|
"",
|
||||||
|
"Großartig! Da du dich jetzt mit Remote Tracking Branches auskennst können wir anfangen, die Geheimnisse hinter `git push`, `fetch` und `pull` zu ergründen. Wir werden uns einen Befehl nach dem anderen vornehmen, aber die Funktionsweisen sind sich sehr ähnlich.",
|
||||||
|
"",
|
||||||
|
"Zunächst schauen wir uns `git push` an. Du hast im Level über Remote Tracking schon mitbekommen, dass Git den Remote Server *und* den Branch herausbekommt, indem es sich die Eigenschaften des aktuell ausgecheckten Branches ansieht (in denen das Remote steht, das der Branch \"trackt\"). Das ist das Verhalten bei keiner Angabe weiterer Optionen -- du kannst bei `git push` aber auch folgende setzen:",
|
||||||
|
"",
|
||||||
|
"`git push <Remote> <Ort>`",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Was \"Ort\" sein soll fragst du? Das klären wir später genau, schauen wir uns zunächst ein Beispiel an:",
|
||||||
|
"",
|
||||||
|
"`git push origin master`",
|
||||||
|
"",
|
||||||
|
"Das bedeutet im Klartext:",
|
||||||
|
"",
|
||||||
|
"\"Geh zum Branch namens `master` in meinem Repository, nimm all seine Commits, dann geh zum Branch `master` auf dem Remote namens `origin`. Leg da alles Commits ab die fehlen und sag mir wenn du fertig bist.\"",
|
||||||
|
"",
|
||||||
|
"Dadurch, dass wir `master` als \"Ort\" angegeben haben, weiß Git *woher* die Commits kommen und *wohin* sie sollen. Es ist im Grunde der Name der Orte, die zwischen zwei Repositorys synchronisiert werden soll.",
|
||||||
|
"",
|
||||||
|
"Dadurch, dass wir Git alles explizit gesagt haben, was es für die Operation wissen muss (durch Angabe von Remote und Ort) ist es vollkommen egal, was gerade ausgecheckt ist."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns noch ein Beispiel an. Beachte was in diesem Fall gerade ausgecheckt ist."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Da haben wir's! `master` wurde auf dem Remote aktualisiert, weil wir beide Optionen angegeben haben."
|
||||||
|
],
|
||||||
|
"command": "git checkout C0; git push origin master",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Was wäre passiert, wenn wir keine Optionen benutzt hätten?"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Der Befehl schlägt fehlt, da `HEAD` nicht auf einem Branch steht, der ein Remote trackt."
|
||||||
|
],
|
||||||
|
"command": "git checkout C0; git push",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Ok, in diesem Level lass und sowohl `foo` als auch `master` auf dem Remote aktualisieren. Um's spannender zu machen, ist `git checkout` in diesem Level deaktiviert."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git push origin master^:foo;git push origin foo:master",
|
"solutionCommand": "git push origin master^:foo;git push origin foo:master",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C6\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"foo\":{\"target\":\"C4\",\"id\":\"foo\",\"remoteTrackingBranchID\":\"o/foo\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/foo\":{\"target\":\"C1\",\"id\":\"o/foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C2\",\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C2\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"foo\":{\"target\":\"C1\",\"id\":\"foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C6\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"foo\":{\"target\":\"C4\",\"id\":\"foo\",\"remoteTrackingBranchID\":\"o/foo\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/foo\":{\"target\":\"C1\",\"id\":\"o/foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C2\",\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C2\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"foo\":{\"target\":\"C1\",\"id\":\"foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Git push arguments -- Expanded!"
|
"en_US": "Git push arguments -- Expanded!",
|
||||||
|
"zh_CN": "Git push 参数2!",
|
||||||
|
"de_DE": "Optionen fü Git Push -- noch mehr!"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember you can admit defeat and type in \"show solution\" :P"
|
"en_US": "Remember you can admit defeat and type in \"show solution\" :P",
|
||||||
|
"zh_CN": "如果你失败了, 可以通过 \"show solution\" 找到解决方案 :P",
|
||||||
|
"de_DE": "Vergiss nicht dass du aufgeben kannst, indem du \"show solution\" eingibst :P"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -58,7 +62,7 @@ exports.level = {
|
||||||
"type": "GitDemonstrationView",
|
"type": "GitDemonstrationView",
|
||||||
"options": {
|
"options": {
|
||||||
"beforeMarkdowns": [
|
"beforeMarkdowns": [
|
||||||
"What if the destination you want to push doesn't exist? No problem! Just give a branch name and git will create the branch on the remote for you"
|
"What if the destination you want to push doesn't exist? No problem! Just give a branch name and git will create the branch on the remote for you."
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"Sweet, that's pretty slick :D"
|
"Sweet, that's pretty slick :D"
|
||||||
|
@ -78,6 +82,146 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## `<place>` argument details",
|
||||||
|
"",
|
||||||
|
"还记得之前课程说的吧, 当为git push 指定master为place时,我们可以设置 要提交的来源 和 提交到目的地. ",
|
||||||
|
"",
|
||||||
|
"你可能想知道-- 如果来源和目的地不一样呢? ",
|
||||||
|
"",
|
||||||
|
"好吧, 很不幸git 不可能做到... 只是个玩笑! 当然是可能的啦:)... git拥有超强的灵活性(几乎不能再多了) ",
|
||||||
|
"",
|
||||||
|
"我们看看下一个幻灯片..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"要为<place> 指定 source 和 destination, 只需要用冒号`:`将二者联结.",
|
||||||
|
"",
|
||||||
|
"`git push origin <source>:<destination>`",
|
||||||
|
"",
|
||||||
|
"这通常被称为<colon refspec>, refspec是一个奇特的名-- 用于git 能识别的位置(比如分支foo 或者 HEAD~1) ",
|
||||||
|
"",
|
||||||
|
"一旦你指定了独立的来源和目的地, 你就可以得到花哨而精确的远程命令, 让我们看看演示! "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"记住, `source` 是git 能理解任何位置:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
" 这是个很迷幻的命令, 但它是合理的 -- git 将foo^解析 为位置, 上传新提交到远端的目的地. "
|
||||||
|
],
|
||||||
|
"command": "git push origin foo^:master",
|
||||||
|
"beforeCommand": "git clone; go -b foo; git commit; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"如果你要push到的destination不存在呢? 没问题! git 会在远端为你创建这个分支!"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"甜蜜吧! 干得漂亮!:D"
|
||||||
|
],
|
||||||
|
"command": "git push origin master:newBranch",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"本节练习, 试着达到可视窗口展示的目标, 记住参数格式哟:",
|
||||||
|
"",
|
||||||
|
"`<source>:<destination>`"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Details zum `<Ort>`-Parameter",
|
||||||
|
"",
|
||||||
|
"Du erinnerst dich von dem vorherigen Level, dass, als wir `master` als \"Ort\" beim `git push` angegeben haben, daraus sowohl die *Quelle* als auch das *Ziel* für die Operation abgeleitet wurden.",
|
||||||
|
"",
|
||||||
|
"Daher fragst du dich vielleicht -- was wenn wir möchten, dass Quelle und Ziel anders sind? Was wenn du Commits von einem lokalen Branch `foo` in den Branch `bar` auf einem Server schieben möchtest?",
|
||||||
|
"",
|
||||||
|
"Tja, leider ist das in Git unmöglich .... ein Scherz! Natürlich ist das möglich. Git besitzt tonnenweise Flexibilität (eher zuviel, als zuwenig).",
|
||||||
|
"",
|
||||||
|
"Und gleich sehen wir, wie das geht ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um sowohl Quelle als auch Ziel im `<Ort>`-Parameter anzugeben, gib sie einfach verbunden mit einem Doppelpunkt ein:",
|
||||||
|
"",
|
||||||
|
"`git push origin <Quelle>:<Ziel>`",
|
||||||
|
"",
|
||||||
|
"Das wird üblicherweise Refspec (Referenz-Spezifikation) genannt. Refspec ist nur ein anderer Name für einen Ort, mit dem Git etwas anfangen kann (wie mit Branch `foo` oder mit `HEAD~2`)",
|
||||||
|
"",
|
||||||
|
"Sobald du Quelle und Ziel separat angibt, kannst du flexibel und präzise entfernte Branches ansteuern. Hier eine Demo:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Vergiss nicht, `Quelle` ist jeder mögliche Ort, mit dem Git etwas anfangen kann:"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Boah! Das ist ein ziemlich abgefahrener Befehl gewesen, aber er ist sinnvoll -- Git hat `foo^` zu einem Commit aufgelöst, alle Commits die bis zu diesem einschließich noch nicht auf dem Server waren hochgeladen und dann dort das Ziel aktualisiert."
|
||||||
|
],
|
||||||
|
"command": "git push origin foo^:master",
|
||||||
|
"beforeCommand": "git clone; go -b foo; git commit; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Was wäre wenn das Ziel des `push` gar nicht existiert? Kein Problem! Wenn das Ziel ein Branch-Name ist, wird Git den Branch auf dem Server einfach anlegen."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Schick, das ist ziemlich praktisch. :D"
|
||||||
|
],
|
||||||
|
"command": "git push origin master:newBranch",
|
||||||
|
"beforeCommand": "git clone; git commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um dieses Level zu schaffen versuch den dargestellten Zielzustand zu erreichen und vergiss nicht das Format:",
|
||||||
|
"",
|
||||||
|
"`<Quelle>:<Ziel>`"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git fetch;git rebase o/master side1;git rebase side1 side2;git rebase side2 side3;git rebase side3 master;git push",
|
"solutionCommand": "git fetch;git rebase o/master side1;git rebase side1 side2;git rebase side2 side3;git rebase side3 master;git push",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\",\"localBranchesThatTrackThis\":null},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":[\"master\"]},\"side1\":{\"target\":\"C2\",\"id\":\"side1\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side2\":{\"target\":\"C4\",\"id\":\"side2\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side3\":{\"target\":\"C7\",\"id\":\"side3\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C1\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"side3\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C8\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C8\":{\"parents\":[\"C1\"],\"id\":\"C8\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\",\"localBranchesThatTrackThis\":null},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":[\"master\"]},\"side1\":{\"target\":\"C2\",\"id\":\"side1\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side2\":{\"target\":\"C4\",\"id\":\"side2\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null},\"side3\":{\"target\":\"C7\",\"id\":\"side3\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"},\"C3\":{\"parents\":[\"C1\"],\"id\":\"C3\"},\"C4\":{\"parents\":[\"C3\"],\"id\":\"C4\"},\"C5\":{\"parents\":[\"C1\"],\"id\":\"C5\"},\"C6\":{\"parents\":[\"C5\"],\"id\":\"C6\"},\"C7\":{\"parents\":[\"C6\"],\"id\":\"C7\"}},\"HEAD\":{\"target\":\"side3\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C8\",\"id\":\"master\",\"remoteTrackingBranchID\":null,\"localBranchesThatTrackThis\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C8\":{\"parents\":[\"C1\"],\"id\":\"C8\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember you can always use the undo or reset commands"
|
"en_US": "Remember you can always use the undo or reset commands",
|
||||||
|
"zh_CN": "你随时都可以使用undo/reset命令.",
|
||||||
|
"de_DE": "Denk dran, du kannst immer undo oder reset benutzen, um deine Befehle zurück zu nehmen."
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Push Master!"
|
"en_US": "Push Master!",
|
||||||
|
"zh_CN": "Push Master!",
|
||||||
|
"de_DE": "Push Master!"
|
||||||
},
|
},
|
||||||
"compareOnlyMasterHashAgnostic": true,
|
"compareOnlyMasterHashAgnostic": true,
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
|
@ -35,7 +39,7 @@ exports.level = {
|
||||||
"type": "GitDemonstrationView",
|
"type": "GitDemonstrationView",
|
||||||
"options": {
|
"options": {
|
||||||
"beforeMarkdowns": [
|
"beforeMarkdowns": [
|
||||||
"Let's see a refresher real quick of how to update `master` and push work"
|
"Let's see a refresher real quick of how to update `master` and push work."
|
||||||
],
|
],
|
||||||
"afterMarkdowns": [
|
"afterMarkdowns": [
|
||||||
"We executed two commands here that:",
|
"We executed two commands here that:",
|
||||||
|
@ -57,7 +61,113 @@ exports.level = {
|
||||||
"* We want to push each one of these features, in order, to the remote",
|
"* We want to push each one of these features, in order, to the remote",
|
||||||
"* The remote has since been updated, so we will need to incorporate that work as well",
|
"* The remote has since been updated, so we will need to incorporate that work as well",
|
||||||
"",
|
"",
|
||||||
":O intense! good luck, completing this level is a big step"
|
":O intense! good luck, completing this level is a big step."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Einen Feature Branch reintegrieren",
|
||||||
|
"",
|
||||||
|
"Nun da du mit `fetch`, `pull`, und `push` vertraut bist sollten wir diese Fähigkeiten mit einem neuen Arbeitsablauf auf die Probe stellen.",
|
||||||
|
"",
|
||||||
|
"Für Entwickler in großen Projekten ist es nicht ungewöhnlich ihre Arbeit in Feature Branches (von `master` abgeleitet) zu erledigen und dann diese Inhalte zu reintegrieren, wenn sie fertig sind. Das ist ähnlich dem vorherigen Level (in dem ein Feature Branch auf den Server geschoben wird), nur mit einem zusätzlichen Schritt.",
|
||||||
|
"",
|
||||||
|
"Einige Entwickler pushen und pullen nur auf dem `master` -- dadurch ist `master` immer aktuell zu seinem Gegenstück auf dem Server (`o/master`).",
|
||||||
|
"",
|
||||||
|
"Für diesen Ablauf werden wir also zwei Dinge kombinieren:",
|
||||||
|
"",
|
||||||
|
"* einen Feature Bran in `master` reintegrieren und",
|
||||||
|
"* vom entfernten Server pushen und pullen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns zur Erinnerung schnell noch mal an wie man den `master` aktualisiert und seine Commits pusht."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Wir haben hier zwei Befehle ausgeführt, die:",
|
||||||
|
"",
|
||||||
|
"* unsere Commits auf die neuen Commits vom Server gepackt und",
|
||||||
|
"* unsere Commits zum Server gepusht haben."
|
||||||
|
],
|
||||||
|
"command": "git pull --rebase; git push",
|
||||||
|
"beforeCommand": "git clone; git commit; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Dieser Level ist ziemlich heftig -- hier ist im Groben der Weg:",
|
||||||
|
"",
|
||||||
|
"* Es gibt drei Feature Branches -- `side1`, `side2` und `side3`.",
|
||||||
|
"* Wir möchten jedes dieser Features, in dieser Reihenfolge, auf den Server bringen.",
|
||||||
|
"* Der Server hat Commits, die wir noch nicht haben, diese müssen also bei uns integriert werden.",
|
||||||
|
"",
|
||||||
|
":O Krass! Viel Erfolg, diesen Level zu schaffen ist ein großer Schritt."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## 合并特性分支",
|
||||||
|
"",
|
||||||
|
"现在你应该很熟悉fetch/pull/push了, 现在我们将这些技能用于一种新的工作流.",
|
||||||
|
"",
|
||||||
|
"在一个大型项目中, 这是非常普遍的 -- 开发者在特性分支(不是`master`)上工作, 工作完成后只做一次合并. 这跟前面课程描述很相像, 不过本节我们会深入一些.",
|
||||||
|
"",
|
||||||
|
"一些开发者只在master上做push/pull —— 这样的话master总是最新的,即与远端(o/master)一致. ",
|
||||||
|
"",
|
||||||
|
"对于这样的工作流, 我们合并两个步骤",
|
||||||
|
"",
|
||||||
|
"* 合并特性分支到`master`",
|
||||||
|
"* 推送并更新远端"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"让我们看看更快的推送流程 "
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"我们执行了两个命令: ",
|
||||||
|
"",
|
||||||
|
"* 将远端的新提交衍合到我们的工作中",
|
||||||
|
"* 向远端推送我们的工作"
|
||||||
|
],
|
||||||
|
"command": "git pull --rebase; git push",
|
||||||
|
"beforeCommand": "git clone; git commit; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"本篇有点儿复杂-- 以下是问题核心",
|
||||||
|
"",
|
||||||
|
"* 这里有三个特性分支 -- `side1` `side2` and `side3`",
|
||||||
|
"* 我需要按顺序将这三分支推送到远端.",
|
||||||
|
"* 因为远端已经被更新过了, 所以我们需要先做合并!",
|
||||||
|
"",
|
||||||
|
":O 紧张了? 祝好运! 完成了本节, 你就前进了一大步啦! "
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git commit;git checkout o/master;git commit",
|
"solutionCommand": "git commit;git checkout o/master;git commit",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\"}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Remote Branches"
|
"en_US": "Remote Branches",
|
||||||
|
"zh_CN": "Remote Branches",
|
||||||
|
"de_DE": "Branches auf entfernten Servern"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Pay attention to the ordering -- commit on master first!"
|
"en_US": "Pay attention to the ordering -- commit on master first!",
|
||||||
|
"zh_CN": "Pay attention to the ordering -- commit on master first!",
|
||||||
|
"de_DE": "Beachte die Sortierung -- committe zuerst auf dem master!"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -43,7 +47,7 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"Unfortunately the full name of `origin` does not fit in our UI, so we use `o` as shorthand :( Just remember when you're using real git, your remote is probably going to be named `origin`!",
|
"Unfortunately the full name of `origin` does not fit in our UI, so we use `o` as shorthand :( Just remember when you're using real git, your remote is probably going to be named `origin`!",
|
||||||
"",
|
"",
|
||||||
"That's a lot to take in, so let's see this all in action."
|
"That's a lot to take in, so let's see all this in action."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -64,7 +68,129 @@ exports.level = {
|
||||||
"type": "ModalAlert",
|
"type": "ModalAlert",
|
||||||
"options": {
|
"options": {
|
||||||
"markdowns": [
|
"markdowns": [
|
||||||
"To finish this level, commit once off of `master` and once after checking out `o/master`. This will help drive home how remote branches behave differently, and they only update to reflect the state of the remote"
|
"To finish this level, commit once off of `master` and once after checking out `o/master`. This will help drive home how remote branches behave differently, and they only update to reflect the state of the remote."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Branches auf entfernten Servern",
|
||||||
|
"",
|
||||||
|
"Nun da du `git clone` in Aktion gesehen hast, lass uns tiefer in die Materie eintauchen.",
|
||||||
|
"",
|
||||||
|
"Das erste, was dir wahrscheinlich aufgefallen ist, ist dass ein neuer Branch in unserem lokalen Repository aufgetaucht ist, namens `o/master`. Diese Art von Branch nennt sich _Remote_ Branch; er hat besondere Eigenschaften, weil er einem bestimmten Zweck dient.",
|
||||||
|
"",
|
||||||
|
"Ein Remote Branch bildet den Zustand des entsprechenden Branch in einem entfernten Repository ab (dem Zustand in dem der Branch war, als du das letzte mal das entfernte Repository angesprochen hast). Er hilft dir, den Unterschied zwischen deinem lokalen Branch und dem Gegenstück auf dem Server zu sehen -- eine nötige Information, bevor du deine Arbeit mit anderen teilen kannst.",
|
||||||
|
"",
|
||||||
|
"Remote Branches besitzen die besondere Eigenschaft dein Repository in den \"Detached `HEAD`\" Zustand zu versetzen, wenn du sie auscheckst. Git macht das absichtlich so, denn du kannst nicht direkt auf Remote Branches arbeiten; du musst auf Kopien von ihnen arbeiten und deine Änderungen von dort auf den entfernten Server schieben (wonach der Remote Branch dann auch bei dir aktualisiert wird)."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Was heißt `o/`?",
|
||||||
|
"",
|
||||||
|
"Du fragst dich vielleicht was das `o/` am Anfang des Namens des Remote Branch bedeuten soll. Nun, Namen von Remote Branches folgen einer (zwingenden) Konvention -- sie werden mit diesem Format gebildet:",
|
||||||
|
"",
|
||||||
|
"* `<Name des Remote>/<Name des Branches>`",
|
||||||
|
"",
|
||||||
|
"Wenn du also einen Remote Branch namens `o/master` hast, ist es eine Abbildung des Branches `master` auf dem Server, der in deinem Repository als `origin` bekannt ist.",
|
||||||
|
"",
|
||||||
|
"Die meisten Entwickler nennen das Haupt-Remote tatsächlich `origin` und nicht `o`. Das ist so verbreitet, dass Git den entfernten Server von dem man ein `git clone` macht tatsächlich als `origin` im Clone speichert.",
|
||||||
|
"",
|
||||||
|
"Leider passt der ganze Name, `origin`, nicht in unsere Darstellung, deshalb benutzen wir hier kurz `o`. :( Merk dir einfach: wenn du echtes Git benutzt werden die Remotes meistens `origin` heißen!",
|
||||||
|
"",
|
||||||
|
"So, das war eine Menge zu verdauen, schauen wir uns das in Aktion an."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Checken wir mal einen Remote Branch aus und schauen was passiert"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Wie du siehst setzt uns Git in den \"Detached `HEAD`\" Modus und aktualisiert dann nach dem Commit nicht den Branch `o/master`. Das liegt daran, dass der Remote Branch nur aktualisiert wird, wenn sich der entsprechende Branch auf dem Remote verändert."
|
||||||
|
],
|
||||||
|
"command": "git checkout o/master; git commit",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Um diesen Level zu bewältigen musst du einen Commit in `master` machen und einen nachdem du `o/master` ausgecheckt hast. Das illustriert noch einmal wie sich Branches und Remote Branches unterschiedlich verhalten und dass letztere sich nur verändern, wenn sich ihr Zustand auf dem entfernten Server ändert."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"zh_CN": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## Git 远端分支",
|
||||||
|
"",
|
||||||
|
"现在你看过`git clone`的执行了, 让我们深入下去看看发生了什么?",
|
||||||
|
"",
|
||||||
|
"第一件事, 你应该注意到在我们的本地仓库出现了一个新的分支`o/master` , 这种类型的分支叫 _remote_ branch (就叫远端分支好了), 远端分支拥有一些用于特别目的的特殊属性.",
|
||||||
|
"",
|
||||||
|
"远程分支反映了无端仓库的状态(你上次和远端仓库通信的时刻). 这会帮助你理解本地工作与公共工作的不同 -- 这是你与别人分享工作前很重要的一步.",
|
||||||
|
"",
|
||||||
|
"检出远端分支时, 有一个特别的属性 -- 你会被置于一个分离式的`HEAD`. 因为你不能在这些分支上直接操作, 你必须在别的地方完成你的工作, 再与远端分享你的工作. "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### What is `o/`?",
|
||||||
|
"",
|
||||||
|
"你可能想知道这些远端分支的头`o/` 意味着什么. 好吧, 远端分支有一个全名规范 -- 它们以这样的格式显示: ",
|
||||||
|
"",
|
||||||
|
"* `<remote name>/<branch name>`",
|
||||||
|
"",
|
||||||
|
"提示, 如果你看到一个分支命名为`o/master`, 那分支名就是`master`, 远端的名就是 `o`. ",
|
||||||
|
"",
|
||||||
|
"大多数的开发者会将它们的远端命名为`origin`, 而非`o`. 这是如此的普遍, 以致于当你用`git clone` 时,得到的仓库名就是 `origin`",
|
||||||
|
"",
|
||||||
|
"不幸的是, 我们的UI不适用`origin`, 我们使用缩写`o`, :) 记住, 当你使用真正的git时, 你的远程仓库很可能被命名为`origin`! ",
|
||||||
|
"",
|
||||||
|
"说了这么多, 让我们看看实例."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"如果检出remote分支, 会发生什么呢?"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"正如你所见, git 处于了分离`HEAD`, 当添加新的提交时, `o/master`不被更新, 这是因为`o/master` 仅伴随远端更新而更新."
|
||||||
|
],
|
||||||
|
"command": "git checkout o/master; git commit",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"尝试完成本节, 在`master`上做一个提交, 再检出`o/master`后再做一提交. 这展示了远端分支行为上的不同, 他们的更新只是反映了远端的状态."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git push origin :foo;git fetch origin :bar",
|
"solutionCommand": "git push origin :foo;git fetch origin :bar",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/foo\":{\"target\":\"C1\",\"id\":\"o/foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"foo\":{\"target\":\"C1\",\"id\":\"foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null},\"o/foo\":{\"target\":\"C1\",\"id\":\"o/foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":null},\"foo\":{\"target\":\"C1\",\"id\":\"foo\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Source of nothing"
|
"en_US": "Source of nothing",
|
||||||
|
"zh_CN": "没有source",
|
||||||
|
"de_DE": "Die Quelle des Nichts"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "The branch command is disabled for this level so you'll have to use fetch!"
|
"en_US": "The branch command is disabled for this level so you'll have to use fetch!",
|
||||||
|
"zh_CN": "本节的分支命令被禁用了, 你只能使用fetch! ",
|
||||||
|
"de_DE": "Der branch Befehl ist für diesen Level inaktiv, du musst also fetch benutzen"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -61,6 +65,113 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### 奇葩的`<source>`",
|
||||||
|
"",
|
||||||
|
"Git abuses the `<source>` parameter in two weird ways. These two abuses come from the fact that you can technically specify \"nothing\" as a valid `source` for both git push and git fetch. The way you specify nothing is via an empty argument:",
|
||||||
|
"有两种罕见的情况, git 不需要 `<source>`. 这基于这样一个事实-- 技术上说就是你不指定<source>. 这是通过空参数实现的",
|
||||||
|
"",
|
||||||
|
"* `git push origin :side`",
|
||||||
|
"* `git fetch origin :bugFix`",
|
||||||
|
"",
|
||||||
|
"我们看看这是怎么进行的..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"如果给push传一个空参数会如何呢? 远端会删除分支! "
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"就是这样子, 我们通过给push传空值source, 成功删除了远端的`foo`分支, 这真有意思..."
|
||||||
|
],
|
||||||
|
"command": "git push origin :foo",
|
||||||
|
"beforeCommand": "git clone; git push origin master:foo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"如果给fetch传空<source>, 那本地会创建一个新分支."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"很神奇吧! 但无论怎么说, 这就是git !"
|
||||||
|
],
|
||||||
|
"command": "git fetch origin :bar",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"快速测试 -- 删除远端的分支, 再在本地创建新的分支! "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Die Eigentümlichkeiten von `<Quelle>`",
|
||||||
|
"",
|
||||||
|
"Git \"missbraucht\" den `<Quelle>`-Parameter in zwei Fällen. Diese rühren daher, dass man technisch gesehen \"nichts\" als gültige `<Quelle>` sowohl für `git push` als auch für `git fetch` angeben kann. Das macht man so:",
|
||||||
|
"",
|
||||||
|
"* `git push origin :side`",
|
||||||
|
"* `git fetch origin :bugFix`",
|
||||||
|
"",
|
||||||
|
"Schauen wir, was das bewirkt ..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Was passiert, wenn man \"nichts\" auf einen entfernten Branch pusht? Er wird gelöscht!"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Und schon haben wir `foo` erfolgreich auf dem Remote gelöscht, weil wir \"Leere\" darauf geschoben haben. Ist auf seine Weise irgendwie logisch ..."
|
||||||
|
],
|
||||||
|
"command": "git push origin :foo",
|
||||||
|
"beforeCommand": "git clone; git push origin master:foo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Und weiter: indem man \"nichts\" von einem Remote in sein lokales Repository zieht, erstellt man tatsächlich einen neuen Branch."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Ziemlich abgefahren / bizarr, aber was soll's. Das ist halt Git."
|
||||||
|
],
|
||||||
|
"command": "git fetch origin :bar",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Das ist ein kurzer Level -- lösch einfach den Remote Branch und erstelle einen neuen Branch mit `git fetch`, um ihn zu lösen."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@ exports.level = {
|
||||||
"solutionCommand": "git checkout -b side o/master;git commit;git pull --rebase;git push",
|
"solutionCommand": "git checkout -b side o/master;git commit;git pull --rebase;git push",
|
||||||
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
"startTree": "{\"branches\":{\"master\":{\"target\":\"C1\",\"id\":\"master\",\"remoteTrackingBranchID\":\"o/master\"},\"o/master\":{\"target\":\"C1\",\"id\":\"o/master\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"},\"originTree\":{\"branches\":{\"master\":{\"target\":\"C2\",\"id\":\"master\",\"remoteTrackingBranchID\":null}},\"commits\":{\"C0\":{\"parents\":[],\"id\":\"C0\",\"rootCommit\":true},\"C1\":{\"parents\":[\"C0\"],\"id\":\"C1\"},\"C2\":{\"parents\":[\"C1\"],\"id\":\"C2\"}},\"HEAD\":{\"target\":\"master\",\"id\":\"HEAD\"}}}",
|
||||||
"name": {
|
"name": {
|
||||||
"en_US": "Remote Tracking"
|
"en_US": "Remote Tracking",
|
||||||
|
"zh_CN": "Remote Tracking",
|
||||||
|
"de_DE": "Remote Tracking"
|
||||||
},
|
},
|
||||||
"hint": {
|
"hint": {
|
||||||
"en_US": "Remember there are two ways to set remote tracking!"
|
"en_US": "Remember there are two ways to set remote tracking!",
|
||||||
|
"zh_CN": "有两种设置无端跟踪的方法!",
|
||||||
|
"de_DE": "Nicht vergessen, es gibt zwei Arten Remote Tracking einzurichten!"
|
||||||
},
|
},
|
||||||
"startDialog": {
|
"startDialog": {
|
||||||
"en_US": {
|
"en_US": {
|
||||||
|
@ -35,11 +39,13 @@ exports.level = {
|
||||||
"",
|
"",
|
||||||
"You may be wondering how this property got set on the `master` branch when you didn't run any commands to specify it. Well, when you clone a repository with git, this property is actually set for you automatically. ",
|
"You may be wondering how this property got set on the `master` branch when you didn't run any commands to specify it. Well, when you clone a repository with git, this property is actually set for you automatically. ",
|
||||||
"",
|
"",
|
||||||
"During a clone, git creates a remote branch for every branch on the remote (aka branches like `o/master`) and then, for each remote branch, creates a local branch to *track* that remote branch (aka `master`). Thats why you may have seen the following command output:",
|
"During a clone, git creates a remote branch for every branch on the remote (aka branches like `o/master`). It then creates a local branch that tracks the currently active branch on the remote, which is `master` in most cases.",
|
||||||
"",
|
"",
|
||||||
" local branch \"master\" set to track remote branch \"o/master\"",
|
"Once git clone is complete, you only have one local branch (so you aren't overwhelmed) but you can see all the different branches on the remote (if you happen to be very curious). It's the best of both worlds!",
|
||||||
"",
|
"",
|
||||||
"When running `git clone`."
|
"This also explains why you may see the following command output when cloning:",
|
||||||
|
"",
|
||||||
|
" local branch \"master\" set to track remote branch \"o/master\""
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -124,6 +130,233 @@ exports.level = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"zh_CN":{
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Remote-Tracking branches",
|
||||||
|
"",
|
||||||
|
"在前几节课程中有件事儿挺神奇的, git 好像知道`master`与`o/master`是相关的. 当然, 这些分支的名字是相同的, 所以可能是这种逻辑连接了远端的master分支和本地的master分支, 其实这种连接在以下两种情况下清楚体现: ",
|
||||||
|
"",
|
||||||
|
"* pull操作时, 我们下载提交到o/master并且合并到本地master分支。隐含的合并目标由此连接确定.",
|
||||||
|
"* push操作时, 我们把工作从`master`推到远端的`master`(同时会更新远端的副本`o/master`) 这个推送的目的地也是由这种连接确定的! ",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"## 远端跟踪",
|
||||||
|
"",
|
||||||
|
"长话短说, `master` 和 `o/master` 的连接关系就是 分支属性\"remote tracking\" (我们叫远端跟踪好啦). `master` 被设定为跟踪 `o/master` -- 这就是隐含的合并(merge)/推送(push)目的地.",
|
||||||
|
"",
|
||||||
|
"你可以想知道这个属性是怎么被设定的? 你并没有用命令指定过这个属性呀! 好吧, 当你克隆仓库的时候, 这个属性就存在了. ",
|
||||||
|
"",
|
||||||
|
"当你克隆时, git会创建跟踪分支(就像`o/master`), 对于每个远端分支, 创建一个跟踪远端分支的本地分支(`master`), 所以你经常会看到这个的命令输出:",
|
||||||
|
"",
|
||||||
|
" local branch \"master\" set to track remote branch \"o/master\"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### 我能自己指定这个属性吗?",
|
||||||
|
"",
|
||||||
|
"当然可以啦! 你可以让做生意分支跟踪`o/master`, 然后分支就会隐含push的destination(`o/master`) 以及merge的target (`o/master`). 这意味着你可以在分支`totalllyNotMaster`上执行`git push`, 将工作推送到远端的`master`.",
|
||||||
|
"",
|
||||||
|
"有两种方法设置这个属性, 第一种就是通过远端分支检出一个新的分支, 执行: ",
|
||||||
|
"",
|
||||||
|
"`git checkout -b totallyNotMaster o/master`",
|
||||||
|
"",
|
||||||
|
"这样就创建了一个跟踪 `o/master` 的 新分支`totallyNotMaster`. "
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"说得够多了, 我们看看演示! 我们检出一个名叫`foo`的新分支, 然后让其跟踪远端的`master`."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"正如你所看到的, 我们使用了隐含的目标`o/master`来更新`foo`分支. 注意, master未被更新!"
|
||||||
|
],
|
||||||
|
"command": "git checkout -b foo o/master; git pull",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"git push 同样适用这一原则"
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"我们将一个不叫`master`的分支工作 推送到的远端的`master`."
|
||||||
|
],
|
||||||
|
"command": "git checkout -b foo o/master; git commit; git push",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### 方法#2",
|
||||||
|
"",
|
||||||
|
"另一种追踪远端分支的方法就是使用选项 : `git branch -u` . ",
|
||||||
|
"",
|
||||||
|
"`git branch -u o/master foo`",
|
||||||
|
"",
|
||||||
|
"这样`foo` 就会跟踪`o/master`了. 如果你处于foo分支, 那么可以省略 foo",
|
||||||
|
"",
|
||||||
|
"`git branch -u o/master`",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"看看实际的效果..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"结果跟之前一样, 这个命令的意义更精确!"
|
||||||
|
],
|
||||||
|
"command": "git branch -u o/master foo; git commit; git push",
|
||||||
|
"beforeCommand": "git clone; git checkout -b foo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"好了! 本节我们在不检出`master`的情况下将工作推送到的远端的`master`. 因为这是高级课程, 我会让你自己摸索出技巧! :P"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"de_DE": {
|
||||||
|
"childViews": [
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Remote Tracking Branches",
|
||||||
|
"",
|
||||||
|
"In den letzten paar Leveln wirkte es womöglich etwas \"magisch\", dass Git automatisch wusste, dass der Branch `master` irgendwie mit `o/master` verwandt ist. Klar, sie haben ähnliche Namen und daher mag es logisch erscheinen sie in Verbindung zu bringen, aber offensichtlich wird es in zwei Szenarien:",
|
||||||
|
"",
|
||||||
|
"* Beim `pull` werden Commits in `o/master` heruntergeladen und dann per *Merge* in den Branch `master` gebracht. Aus der Verbindung zwischen den beiden Branches leitet sich das Ziel des Merges ab.",
|
||||||
|
"* Beim `push` werden Commits vom `master` auf den `master` auf dem Remote Server geschoben (und die Änderung _danach_ in `o/master` abgebildet). Das *Ziel* des Push wird aus der Verbindung zwischen `master` und `o/master` abgeleitet.",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Langer Rede kurzer Sinn, die Verbindung zwischen `master` und `o/master` ist einfach die Eigenschaft des \"Remote Tracking\" dieser Branches. `master` ist so eingestellt, dass er `o/master` trackt -- das heißt es gibt ein implizites Ziel für `pull` und `push` Operationen auf dem `master` Branch.",
|
||||||
|
"",
|
||||||
|
"Du fragst dich vielleicht wieso diese Eigenschaft auf dem `master` definiert ist, wenn du das doch gar nicht explizit gemacht hast. Naja, beim Clonen eines Repository macht Git das für den `master` automatisch.",
|
||||||
|
"",
|
||||||
|
"Während des Clonens erstellt Git einen Remote Branch für jeden Branch, den es auf dem Remote Server findet (also Branches wie `o/master`); dann erstellt es für den Branch, auf den auf dem entfernten Server `HEAD` zeigt (meistens `master`) automatisch einen lokalen Branch und stellt ihn so ein, dass er sein Gegenstück auf dem Server trackt. Deswegen hast du beim clonen vielleicht schon mal dies gesehen:",
|
||||||
|
"",
|
||||||
|
" local branch \"master\" set to track remote branch \"o/master\""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Kann ich das auch selbst machen?",
|
||||||
|
"",
|
||||||
|
"Na klar! Du kannst jeden beliebigen Branch so einstellen, dass er `o/master` trackt, und wenn du das tust wird der Branch dieselben impliziten Zielangaben für `push` und `pull` haben wie `master`. Du kannst also `git push` auf dem Branch `absolut_nicht_master` ausführen und deine Commits auf `master` auf dem entfernten Server schieben lassen.",
|
||||||
|
"",
|
||||||
|
"Es gibt zwei Möglichkeiten diese Eigenschaft zu definieren. Die erste ist, einen neuen lokalen Branch von einem Remote Branch auszuchecken. Wenn man",
|
||||||
|
"",
|
||||||
|
" git checkout -b absolut_nicht_master o/master",
|
||||||
|
"",
|
||||||
|
"eingibt, wir ein neuer lokaler Branch namens `absolut_nicht_master` angelegt, der `o/master` trackt."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Genug gequatscht, schauen wir uns eine Demonstration an! Wir checken einen neuen Branch `foo` aus, so dass er `master` auf dem Server trackt."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Wie du siehst benutzen wir der implizite Ziel beim `pull` um `foo` zu aktualisieren. Beachte, dass `master` nicht aktualisiert wird."
|
||||||
|
],
|
||||||
|
"command": "git checkout -b foo o/master; git pull",
|
||||||
|
"beforeCommand": "git clone; git fakeTeamwork"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Das gilt auch für `git push`."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Bämm. Wir haben unsere Commits auf den `master` auf dem Server geschoben, obwohl unser lokaler Branch völlig anders heißt."
|
||||||
|
],
|
||||||
|
"command": "git checkout -b foo o/master; git commit; git push",
|
||||||
|
"beforeCommand": "git clone"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"### Methode 2",
|
||||||
|
"",
|
||||||
|
"Noch eine Möglichkeit um Remote Tracking auf einem Branch einzustellen, ist einfach `git branch -u` zu benutzen. Wenn man",
|
||||||
|
"",
|
||||||
|
" git branch -u o/master foo",
|
||||||
|
"",
|
||||||
|
"eingibt, wir damit der lokale Branch `foo` so eingestellt, dass er `o/master` trackt. Den Namen des lokalen Branch kannst du auch weglassen, falls du ihn eh aktuell ausgecheckt hast:",
|
||||||
|
"",
|
||||||
|
" git branch -u o/master",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "GitDemonstrationView",
|
||||||
|
"options": {
|
||||||
|
"beforeMarkdowns": [
|
||||||
|
"Schauen wir uns auch diese Methode noch an ..."
|
||||||
|
],
|
||||||
|
"afterMarkdowns": [
|
||||||
|
"Genau wie vorher, nur ein bisschen ausführlicherer Befehl. Schick!"
|
||||||
|
],
|
||||||
|
"command": "git branch -u o/master foo; git commit; git push",
|
||||||
|
"beforeCommand": "git clone; git checkout -b foo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ModalAlert",
|
||||||
|
"options": {
|
||||||
|
"markdowns": [
|
||||||
|
"Ok. In diesem Level muss du Commits auf den `master` auf dem Server schieben, *ohne* den lokalen `master` ausgecheckt zu haben. Den Rest kannst du selbst herausfinden, schließlich ist das hier für Fortgeschrittene. :P"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,19 @@ p {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.githubLink {
|
||||||
|
z-index: 2;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.githubLink {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
div.modalTerminal a {
|
div.modalTerminal a {
|
||||||
color: rgb(253, 152, 209);
|
color: rgb(253, 152, 209);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -211,11 +224,11 @@ body.hgMode #mainVisSpace .modeText.hgMode {
|
||||||
/* Some interface things */
|
/* Some interface things */
|
||||||
|
|
||||||
div.canvasTerminalHolder {
|
div.canvasTerminalHolder {
|
||||||
width: 100%;
|
height: 0;
|
||||||
height: 100%;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#canvasHolder {
|
#canvasHolder {
|
||||||
|
@ -242,29 +255,9 @@ body.hgMode .visBackgroundColor {
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.canvasTerminalHolder > div.terminal-window-holder {
|
|
||||||
margin: 100px 0;
|
|
||||||
height: 100%;
|
|
||||||
-webkit-transform: translate3d(0,0,0);
|
|
||||||
-moz-transform: translate3d(0,0,0);
|
|
||||||
-o-transform: translate3d(0,0,0);
|
|
||||||
-ms-transform: translate3d(0,0,0);
|
|
||||||
transform: translate3d(0,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
div.canvasTerminalHolder > div.terminal-window-holder.slideOut {
|
|
||||||
-webkit-transform: translate3d(-150%,0,0);
|
|
||||||
-moz-transform: translate3d(-150%,0,0);
|
|
||||||
-o-transform: translate3d(-150%,0,0);
|
|
||||||
-ms-transform: translate3d(-150%,0,0);
|
|
||||||
transform: translate3d(-150%,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
div.canvasTerminalHolder > div.terminal-window-holder > div.wrapper {
|
div.canvasTerminalHolder > div.terminal-window-holder > div.wrapper {
|
||||||
margin: 0 20px 0px 20px;
|
height: 100%;
|
||||||
height: 80%;
|
box-shadow: 0 0 12px rgb(0,0,0);
|
||||||
box-shadow: 0 0 30px rgb(0,0,0);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 0 0 5px 5px;
|
border-radius: 0 0 5px 5px;
|
||||||
}
|
}
|
||||||
|
@ -300,10 +293,11 @@ div.canvasTerminalHolder > div.terminal-window-holder div.inside {
|
||||||
|
|
||||||
div.canvasTerminalHolder > div.terminal-window-holder {
|
div.canvasTerminalHolder > div.terminal-window-holder {
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
|
min-width: 500px;
|
||||||
|
overflow: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Toolbar */
|
/* Toolbar */
|
||||||
|
|
||||||
div.toolbar {
|
div.toolbar {
|
||||||
/* borrowed from try.github.com along with a bunch of other things */
|
/* borrowed from try.github.com along with a bunch of other things */
|
||||||
background-image: -webkit-linear-gradient(top, #EFEDEE, #C1C1C1);
|
background-image: -webkit-linear-gradient(top, #EFEDEE, #C1C1C1);
|
||||||
|
@ -332,7 +326,44 @@ div.toolbar.level-toolbar {
|
||||||
background-image: -ms-linear-gradient(top, #B2FF2E, #8AD247);
|
background-image: -ms-linear-gradient(top, #B2FF2E, #8AD247);
|
||||||
background-image: linear-gradient(top, #B2FF2E, #8AD247);
|
background-image: linear-gradient(top, #B2FF2E, #8AD247);
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
height: 50px;
|
height: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toolbar.level-toolbar button {
|
||||||
|
font-size: 12px;
|
||||||
|
border: 1px solid #888;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background-image: -webkit-linear-gradient(top, #EFEDEE, #C1C1C1);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toolbar div.clearfix {
|
||||||
|
zoom: 1;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toolbar div.clearfix:after {
|
||||||
|
clear: both;
|
||||||
|
content: ".";
|
||||||
|
display: block;
|
||||||
|
font-size: 0;
|
||||||
|
height: 0;
|
||||||
|
line-height: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toolbar div.showGoalWrapper {
|
||||||
|
float: left;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toolbar div.levelNameWrapper {
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
top: 5px;
|
||||||
|
margin: 0 100px;
|
||||||
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.levelToolbarSpan {
|
span.levelToolbarSpan {
|
||||||
|
@ -568,6 +599,8 @@ li.rebaseEntry,
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
box-shadow: -1px -1px 5px rgba(0,0,0,0.3);
|
box-shadow: -1px -1px 5px rgba(0,0,0,0.3);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
max-width: 500px;
|
||||||
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.helperBar i {
|
.helperBar i {
|
||||||
|
@ -581,6 +614,10 @@ li.rebaseEntry,
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.helperBar a.exit {
|
||||||
|
float: right
|
||||||
|
}
|
||||||
|
|
||||||
.helperBar a:after {
|
.helperBar a:after {
|
||||||
content: ' \b7';
|
content: ' \b7';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
@ -590,10 +627,15 @@ li.rebaseEntry,
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.helperBar a:nth-last-child(2):after,
|
||||||
.helperBar a:last-child:after {
|
.helperBar a:last-child:after {
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.helperBar.BaseHelperBar a:nth-last-child(2):after {
|
||||||
|
content: ' \b7';
|
||||||
|
}
|
||||||
|
|
||||||
div.helperBar {
|
div.helperBar {
|
||||||
-webkit-transform: translate3d(150%,0,0);
|
-webkit-transform: translate3d(150%,0,0);
|
||||||
-moz-transform: translate3d(150%,0,0);
|
-moz-transform: translate3d(150%,0,0);
|
||||||
|
@ -608,6 +650,11 @@ div.helperBar.show {
|
||||||
-o-transform: translate3d(0,0,0);
|
-o-transform: translate3d(0,0,0);
|
||||||
-ms-transform: translate3d(0,0,0);
|
-ms-transform: translate3d(0,0,0);
|
||||||
transform: translate3d(0,0,0);
|
transform: translate3d(0,0,0);
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.helperBar.show.BaseHelperBar {
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#commandLineBar,
|
#commandLineBar,
|
||||||
|
@ -710,6 +757,10 @@ div.modalView.box.inFront.show {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.terminal-window-holder {
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
.terminal-window .inside {
|
.terminal-window .inside {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="mainVisSpace" class="box flex1 horizontal transitionAll visBackgroundColor">
|
<div id="mainVisSpace" class="box flex2 horizontal transitionAll visBackgroundColor">
|
||||||
<span class="modeText transitionOpacity gitMode">
|
<span class="modeText transitionOpacity gitMode">
|
||||||
Git
|
Git
|
||||||
</span>
|
</span>
|
||||||
|
@ -75,6 +75,12 @@
|
||||||
Hg
|
Hg
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- If you drag the goal window to the right side of the screen, this gets shown and causes
|
||||||
|
the main visualization to squeeze a bit. This way, you could have the goal window hang out
|
||||||
|
on the right side of the screen and still see the repo visualization. -->
|
||||||
|
<div id="goalPlaceholder" class="box flex1 visBackgroundColor" style="display: none;"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="canvasHolder">
|
<div id="canvasHolder">
|
||||||
|
@ -82,7 +88,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- lol inline styles -->
|
<!-- lol inline styles -->
|
||||||
<a href="https://github.com/pcottle/learnGitBranching" target="_blank" style="z-index: 99; position: fixed; top: 0; right: 0">
|
<a class="githubLink" href="https://github.com/pcottle/learnGitBranching" target="_blank">
|
||||||
<img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub">
|
<img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -121,14 +127,14 @@
|
||||||
<script type="text/html" id="helper-bar-template">
|
<script type="text/html" id="helper-bar-template">
|
||||||
<% for(var i = 0; i < items.length; i++) { %>
|
<% for(var i = 0; i < items.length; i++) { %>
|
||||||
<% if (items[i].text) { %>
|
<% if (items[i].text) { %>
|
||||||
<a data-id="<%= items[i].id %>"><%= items[i].text %></a>
|
<a data-id="<%= items[i].id %>" class="<%=items[i].id%>"><%= items[i].text %></a>
|
||||||
<% } else if (items[i].newPageLink) { %>
|
<% } else if (items[i].newPageLink) { %>
|
||||||
<a data-id="<%= items[i].id %>"
|
<a data-id="<%= items[i].id %>"
|
||||||
target="_blank" href="<%= items[i].href %>">
|
target="_blank" href="<%= items[i].href %>"class="<%=items[i].id%>">
|
||||||
<i data-id="<%= items[i].id %>" class="icon-<%= items[i].icon %>"></i>
|
<i data-id="<%= items[i].id %>" class="icon-<%= items[i].icon %>"></i>
|
||||||
</a>
|
</a>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<a data-id="<%= items[i].id %>">
|
<a data-id="<%= items[i].id %>" class="<%=items[i].id%>">
|
||||||
<i data-id="<%= items[i].id %>" class="icon-<%= items[i].icon %>"></i>
|
<i data-id="<%= items[i].id %>" class="icon-<%= items[i].icon %>"></i>
|
||||||
</a>
|
</a>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
@ -137,7 +143,11 @@
|
||||||
|
|
||||||
<script type="text/html" id="level-toolbar-template">
|
<script type="text/html" id="level-toolbar-template">
|
||||||
<div class="toolbar level-toolbar box vertical center transitionAll hidden">
|
<div class="toolbar level-toolbar box vertical center transitionAll hidden">
|
||||||
<div>
|
<div class="clearfix">
|
||||||
|
<div class="showGoalWrapper">
|
||||||
|
<button id="show-goal" type="button">Show Goal</button>
|
||||||
|
</div>
|
||||||
|
<div class="levelNameWrapper">
|
||||||
<i class="icon-bolt"></i>
|
<i class="icon-bolt"></i>
|
||||||
Level
|
Level
|
||||||
<span class="levelToolbarSpan">
|
<span class="levelToolbarSpan">
|
||||||
|
@ -145,6 +155,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/html" id="modal-view-template">
|
<script type="text/html" id="modal-view-template">
|
||||||
|
@ -184,8 +195,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box flex3">
|
|
||||||
</div>
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/html" id="terminal-window-template">
|
<script type="text/html" id="terminal-window-template">
|
||||||
|
|
12
todo.txt
12
todo.txt
|
@ -1,17 +1,14 @@
|
||||||
Big Things
|
Big Things
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
[ ] compare settings for a level!!! integrated into builder...
|
[ ] compare settings for a level!!! integrated into builder...
|
||||||
|
[ ] casperjs for visuals regression testing? it works with canvas so
|
||||||
Origin things:
|
it could be a nice way to move super fast with visuals refactoring
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
[ ] polish visual layout?? needed?
|
|
||||||
|
|
||||||
Medium things:
|
Medium things:
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
[ ] figure out what to do with instant commands (and parse waterfall and the like)
|
[ ] figure out what to do with instant commands (and parse waterfall and the like)
|
||||||
[ ] disable git commands on hg levels (and vice versa)
|
[ ] disable git commands on hg levels (and vice versa)
|
||||||
[ ] make helper bar clickable with goal vis floating
|
[ ] capture unexpected exceptions and print
|
||||||
[ ] make show solution easier
|
|
||||||
|
|
||||||
Small things to implement:
|
Small things to implement:
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -28,6 +25,9 @@ Ideas for cleaning
|
||||||
Done things:
|
Done things:
|
||||||
(I only started this on Dec 17th 2012 to get a better sense of what was done)
|
(I only started this on Dec 17th 2012 to get a better sense of what was done)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
[x] flip trees upside down from command (look at refresh tree as a way to do this)
|
||||||
|
[x] make show solution easier
|
||||||
|
[x] make helper bar clickable with goal vis floating
|
||||||
[x] huge update to level you wrote. that you said is true for
|
[x] huge update to level you wrote. that you said is true for
|
||||||
git fetch and git push (basically) but pull is not the same. basically
|
git fetch and git push (basically) but pull is not the same. basically
|
||||||
its going to ignore where you are during the fetch
|
its going to ignore where you are during the fetch
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue