Subject: [RFC/GSOC] Git Beginner | Warnings for potentially destructive commands

From: Sidhant Sharma <[email-masked]>
Date: Fri, 25 Mar 2016 15:48:49 +0530

Hi,

I made an attempt at writing warning messages for the commands the beginners
will be warned against, and would like to request your comments and feedback
on them. I tried to keep them simple, beginner friendly and educative of the
outcome of those commands.
I'd also like to ask if `git rebase` should be kept in the
list as it may not be bad in most cases, though I prepared a
message for that anyway.

Thanks and regards,
Sidhant Sharma

The current list of graylisted commands is as follows:
$ git rebase
$ git reset --hard
$ git clean -f
$ git gc --prune=now --aggressive
$ git push -f <branch>
$ git push remote [+/:]<branch>
$ git branch -D

Warning messages:

$ ggit rebase

[WARNING] You are about to rebase your commits in <topic-branch> onto the
$BASE_BRANCH, which will essentially replay the work done in $TOPIC_BRANCH
since last merge onto $BASE_BRANCH.
For instance,
Current state:

    o---o---A---B  $BASE_BRANCH
         \
          X---Y  $TOPIC_BRANCH

State after rebasing:

    o---o---A---B---X'---Y'  $BASE_BRANCH
         \
          X---Y  $TOPIC_BRANCH

where X' and Y' are the commits making changes identical to those made by X and
Y respectively.
Rebasing is not usually problematic except in cases when you are rebasing
commits that do not exist in your repository.

$ ggit reset --hard

Resetting to <destination-commit-hash>
[WARNING] You are about to hard reset the current HEAD (master) by <n> commit(s).
This will take you back to commit <destination-commit-hash>, and discard all
changes make thereafter. For instance,
Current state:

    o---o---A---B---C---D---E  $CURRENT_BRANCH

After resetting 3 commits:

    o---o---A---B  $CURRENT_BRANCH

The commits C, D and E and the changes made by them will be lost.
Note that if you make commits on top of B, you would have rewritten the history
and would have trouble restoring it easily.
You can undo this action by resetting the HEAD to the last commit you were on,
which can be seen by running `git reflog`. The first entry (HEAD{1}) points to
the current HEAD location, second entry (HEAD{1}) points to the last position of
your HEAD and so on.
If you want to reset while retaining the changes made since, use --soft instead
of --hard. This will reset without discarding the changes made in the previous
commits.

$ ggit push --force

Pushing changes to $REMOTE/$BRANCH
[WARNING] You are about to purge commits from the <URL of origin> master branch.
For instance,
Current state:

        o---o---o---A---B  master on $ORIGIN_URL
             \
              X---Y---Z  your master

State after forced push:

        o---o---o---X---Y---Z  master on $ORIGIN_URL and your master

Commit A and B will be gone. If other people have worked on top of A or B then
they won't be able to merge their changes easily.

$ ggit push <remote> :<branch> ( ggit push <remote> --delete <branch> )

Pushing changes to $REMOTE/$BRANCH
[WARNING] You are about delete a remote branch, which will result in the loss
of commits made on that branch. This may cause a problem if other people are
working on the branch you are deleting, as they would not be able to push or
merge their changes easily.
You can undo this by pushing the same branch to the remote with upstream flag,
that is, by running:
`$ ggit push -u $REMOTE $BRANCH`
This will work unless you have deleted the branch locally as well. In that case,
you need to restore it first.

$ ggit push <remote> +<branch>
( ggit push <remote> +<basebranch>:<targetbranch> )

Pushing changes to $REMOTE/$BRANCH
[WARNING] You are attempting to push changes from $BASE_BRANCH to $TARGET_BRANCH
while allowing non-fast-forward updates. This can leave unreferenced commits
dangling in the origin repository.
For instance,
Current state:

        o---o---A---B  $REMOTE/$TARGET_BRANCH
             \
              X---Y---Z  your $BASE_BRANCH

State after forced push:

        o---o---A---B    (unnamed branch)
             \
              X---Y---Z  $REMOTE/$TARGET_BRANCH and your $BASE_BRANCH

Commits A and B would no longer belong to a branch with a symbolic name, and so
would be unreachable. Also, people who have based their work on A or B would
have to either merge or rebase after you have pushed.
If you wish to keep both the changesets (A,B and X,Y,Z), you may want to use
`merge` or `rebase`.

$ ggit branch -D
( ggit branch -d -f )

Deleting branch $TARGET_BRANCH
[WARNING] You are about to force delete the $TARGET_BRANCH branch. This will
cause git to delete the branch even if it has not been merged, which may result
in loss of commits. Unless you are confident the branch has been merged, use
`-d` or `--delete` without `--force` which will warn you if the branch has not
been merged.
You can restore a forcefully deleted branch by running:
`$ git branch <branch-name> <sha1>`
where <branch-name> is the name of the branch you wish to restore and <sha1> is
the last commit made to the branch you want to restore. You can find this
information by running `git reflog`.
To undo deletion of this branch, you can run:
`$ ggit branch $TARGET_BRANCH $LAST_COMMIT_SHA`

$ ggit clean -f [<path>]

Cleaning $PATH
[WARNING] You are about to clean $PATH, which will permanently delete all files
and directories present at the given path. Note that it would not be possible to
revert this action, and all files not tracked by git will be list permanently.
If you only wish to see what will be deleted on running `ggit clean`, use the
`-n` or `--dry-run` option.

$ ggit gc --prune=now --aggressive
(or $ ggit  gc --prune=all --aggressive)

Running garbage collection
[WARNING] You are about to prune all objects, regardless of their age or
reachability. The `--aggressive` flag tells git to aggressively optimize the
repository at the cost of taking more time to complete the operation. By setting
`--prune` option to `now` or `all`, you ask git to optimize all objects, and not
just the unreachable ones. Unless the repository is quiescent, you will lose
newly created objects that haven’t been anchored with the refs and end up
corrupting your repository.
It is also not possible to revert the actions taken by `git gc`.

Accepting input:

Are you sure you want to continue? [Y/n]