This is a continuation of article
XX useful tips for mid-level Git users.About reset, unplanned again about alias, about a wonderful filter-branch, about merdzhi and conflict resolution with the help of rerere, about rebase (interactive and not so) and, finally, about servicing your guitar.
')
1. Where does Git`a reset
If you take the most frequent cases when you need to somehow cancel the last commit or change after it, then this will be the git reset command (aka git reset - mixed HEAD) and git reset - hard. The first one removes the last commit from the index, but does not touch the changes in the files, while the second ruthlessly leads both the index and the files to their original appearance ^ W ^ W state at the time of the specified commit.
In other words, you can undo the edits, even if it`s for the gam add you can do $
git reset HEAD (remember the alias git unstage?).
And completely, for example, the last commit (i.e. rewind time at the moment of the penultimate commit) - $
git reset --hard HEAD ^ .
2. Another alias
According to the results of the study history | grep "git" | sort -d | uniq, I added another alias - $
git config --global alias.amend 'commit --amend -C HEAD' - the last commit with the same message is overwritten by the git amend command.
Perhaps I’ll add the -a option to it (not to do git add every time).
3. filter-branch - salvation for rastyapy!
git filter-branch allows more than ample opportunities for manipulations with history.
I became acquainted with this team when I noticed that I kept the combat passwords not in the internal branch, but in the master.
Thank God that I noticed this before pushing to the public repository!
$
git filter-branch --tree-filter "sed -e 's # my_secret_pass # dbpassword #' -e 's # my_db_hostdbhost.tld #' -i settings.py" HEADWith this simple action, I rewrote the passwords in the settings file in each commit.
You can narrow the scope by specifying specifying parameters --index-filter, --msg-filter, --commit-filter - tag-name-filter, and others.
--all means all the brunches.
4. And again about the merdzhi.
Thanks
ghisguth for the tip-off on a potentially useful tool for dealing with conflicts about merging branches.
I myself have not used it yet, but there is already a registered line (so as not to forget) a line in the config file.
So, meet -
git rerere - allows you to record the resolution of conflicts and when re-merzh use them.
Turns on like this - $
git config --global rerere.enabled 1It is useful if there is a long-lived development brunch that exactly conflicts with another brunch (say, a master), then the “learning” of the guitar with the motions during the merge occurs in this sequence: first we do the git pull origin master, we eliminate conflicts, commit and roll back the test merge back - $
git reset --hard HEAD ^ . With a real merge, all the same gestures that we made with our hands will be automatically done.
In fact, git rerere runs without user intervention and without arguments, but you can correct the progress of the work:
Commands: git rerere [clear | diff | status | gc]
clear - Resets the metadata used by rerere if automatic conflict resolution is canceled.
For example, git am [--skip | --abort] or git rebase [--skip | --abort] automatically uses this parameter.
diff — Displays the current status of the conflict resolution. Useful to keep track of what has changed since the conflict was resolved. additional parameters are passed directly to the diff command.
Unlike diff, it displays only the names of files that are tracked to resolve the conflict.
gc - Removes conflicting merge entries that occurred a long time ago. By default, unresolved conflicts older than 15 days and resolved older than 60 days are cleaned. These values ​​are described in gc.rerereunresolved and gc.rerereresolved.
5. About rebase
It has already been said about the re-raise that this command allows you to “move” the changes you made to the top by placing commits from the wizard in the history that “went ahead” during local editing.
There is another interesting application - rebase --onto.
This way you can transfer your commits based on a completely third-party branch.
For example, there is such a picture:
.-x ------------ master
. |
. \ ----- server-experiments
. |
. \ --- http-interface
To finish the branch with the new interface in the wizard, leaving the merge with the server part, you need to do
$
git rebase --onto master http-interfaceAfter that, you can switch to the master and merge branches (git checkout master; git merge http-interface) - as a result, we have a main branch, a new interface poured into it and completely separate - the remaining branch with experiments on the server part.
PROFIT!
You can rebuild not everything, but interactively and selectively - for this you need the option -i (--interactive).
$
git rebase -i master opens the editor with a list of specified commits of the form “command SHA commit_message”.
Teams are:
p | pick - use commit;
e | edit - use commit, but pause for the sake of --amend (the process will stop before the next item so that you can make some special changes - for example, break the change into smaller commits)
s | squash - use commit but merge with previous commit. (an editor window will be opened in the process so that you can build a general commit message. Such a global commit --amend)
Deleting a line will remove the commit.
You can continue the natural course of things with $
git rebase --continue6. Service
If there is an active development and you do not push the code to a remote server, you should periodically perform garbage collection:
$
git gcThis clears up the garbage - removes unattached objects and effectively (re- | y-) packs the remaining ones.
I said about remote servers, because before pushing to another server, objects are processed automatically.
That seems to be all that I would like to say about the gita)