Feature request: add `submit` command
- Dominant language
- Go
- Stars
- 125
- Forks
- 21
- PR merge metrics
- No merged PRs in 30d
Description
# Premise
Git is hard for students in introductory courses (e.g., CS1). Particularly at term's start, when commands like
```
python foo.py
```
or
```
gcc foo.c
./a.out
```
are already quite new to many students (and complicated if something goes wrong), it's just not compelling to add the cognitive overhead of, or instructional time for, commands like
```
git add
git commit
git push
```
in the earliest days of a course, particularly if Git, early on, is used primarily for submitting work (and not yet for actual collaboration or versioning).
Much like computer science itself teaches abstraction, and much like [instructional scaffolding](https://en.wikipedia.org/wiki/Instructional_scaffolding) characterizes many curricula, so can (and, daresay, should) Git be abstracted away until such time as a teacher's students are ready for lessons in Git itself.
# Solution
Provide students with a `gh classroom submit` command that automates the requisite `git-add`, `git-commit`, and `git-push` commands via which to submit their work, executed a la
```
gh classroom submit ORG/REPO [DIR]
```
or
```
gh classroom submit ORG/REPO@BRANCH [DIR]
```
wherein `ORG` is a teacher's org (for GitHub Classroom), `REPO` is a student's repo therein, `BRANCH` is an optional branch therein, and `DIR` is the directory to submit (i.e., push to the remote repo), which would default to `$PWD`.
Alternatively, per @octosteve, a student could be prompted interactively to select an assignment to submit.
## Implementation Details
Underneath the hood, `gh-classroom-submit` would be a [GitHub CLI extension](https://docs.github.com/en/github-cli/github-cli/creating-github-cli-extensions):
1. Clone a student's repo to, e.g., `/tmp` (and optionally check out a particular branch).
2. Effectively remove the contents thereof.
3. Copy the contents of `$PWD` to that directory, git adding and committing the same.
4. Push the commit back to the remote repo.
For maximum compatibility and ease of installation, probably best if `gh-classroom-submit` is implemented as an [interpreted extension](https://docs.github.com/en/github-cli/github-cli/creating-github-cli-extensions#creating-an-interpreted-extension-manually) in Python and distributed via PyPI. That way, students can use it having just Python on their PC or Mac, without additionally needing the GitHub CLI itself, [installation of which](https://github.com/cli/cli#installation) could be a tad more involved, especially for less comfortable students.
Alternatively, if interactive prompts are compelling, using Go might be best, if only to use the same terminal-based GUI libraries that [other extensions](https://github.com/topics/gh-extension) are using. Pre-installation in students' Codespaces, too, would be trivial to automate.
### Pseudocode
Assumes `$ORG`, `$REPO`, and optionally `$BRANCH` are already set, as via command-line arguments or sensible defaults.
```
#!/usr/bin/bash
# We'll clone a bare repo here
export GIT_DIR=$(mktemp -d)
# We'll assume the student's work is in $PWD
export GIT_WORK_TREE="$PWD"
# Clone the remote's .git directory
git clone --bare "git@github.com:$ORG/$REPO" "$GIT_DIR"
# We'll "submit" to this branch
git symbolic-ref HEAD "refs/heads/$BRANCH"
# Let's check out the teacher's .gitignore from the student's remote clone thereof
git checkout main .gitignore
# Let's add everything from $PWD, modulo the .gitignore
git add --all
# Represent this submission with a commit
git commit --allow-empty --allow-empty-message --message ""
# Push the submission to the remote branch
git push origin "refs/heads/$BRANCH"
```
### Upsides
This approach would avoid any merge conflicts altogether (by first cloning the remote repo), as might (all too frequently) happen if a student accepts an assignment, clones the repo locally, starts to make changes locally, and unwittingly then makes changes (and commits) remotely, as via GitHub.com's pencil icon.
Students also have a habit of deleting things they shouldn't, if only because they don't recognize them (e.g., a `.git` directory in their local clone). Alternatively, if students happen to create a new folder locally into which they `cp` their work (not realizing their original folder also had a "hidden" `.git` folder), they might end up without a local repo altogether from which to push. (And the solution then would be a convoluted, manual `git-clone`, then an `rm`, then another `cp` or `mv` or the like, every step of which would (all too frequently) be fraught with potential pitfalls.
To reduce the probability of mistakes and FAQs, then, much better to automate and abstract (at least at term's start) the submission process entirely.
### Alternatives
To resolve cases in which students have induced merge conflicts, as by editing a file on GitHub.com via the pencil icon but wanting to submit different code locally, we could **force-push**. But any solution that risks overwriting history and/or losing work isn't ideal and is best to avoid.
Similarly could we try to resolve what would otherwise be merge conflicts with **`-Xours`**, but that, too, would risk overwriting remote work that would be best to preserve.
Alternatively still, if a student's state resembles
```
remote: A - B - C
local: \ D - E
```
we could try to achieve
```
remote: A - B - C - F
local: A - B - C - F
```
wherein `F == E`, but that would **overwrite local history** (i.e., commits), which is likely to confuse students who consciously made those local commits.
Best, then, for `gh-classroom-submit` to be a consistent abstraction, ignoring the local repo (i.e., `.git`) altogether and worrying only about getting the student's local code to the remote, without losing history locally or remotely. A student could thus actually use Git locally, particularly when learning it for the first time. But submissions would be entirely independent of that local history.
In cases where a student (or teacher) wants students local commits to be reflected in their remote repo, that's when it's time for the "training wheels" to come off, replacing the abstraction that is `gh-classroom-submit` with actual `git` commands that students themselves execute.
Contributor guide
Assessment
This issue has not been assessed yet.