git-mktree
git-name-rev
git-mv
-git-notes
git-pack-redundant
git-pack-objects
git-pack-refs
* automatic typo correction works on aliases as well
-* Initial support for "git notes" implemented.
-
* @{-1} is a way to refer to the last branch you were on. This is
accepted not only where an object name is expected, but anywhere
a branch name is expected. E.g. "git branch --track mybranch @{-1}"
index comparison to the filesystem data in parallel, allowing
overlapping IO's.
-core.notesRef::
- When showing commit messages, also show notes which are stored in
- the given ref. This ref is expected to contain files named
- after the full SHA-1 of the commit they annotate.
-+
-If such a file exists in the given ref, the referenced blob is read, and
-appended to the commit message, separated by a "Notes:" line. If the
-given ref itself does not exist, it is not an error, but means that no
-notes should be printed.
-+
-This setting defaults to "refs/notes/commits", and can be overridden by
-the `GIT_NOTES_REF` environment variable.
-
alias.*::
Command aliases for the linkgit:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation
+++ /dev/null
-git-notes(1)
-============
-
-NAME
-----
-git-notes - Add/inspect commit notes
-
-SYNOPSIS
---------
-[verse]
-'git-notes' (edit | show) [commit]
-
-DESCRIPTION
------------
-This command allows you to add notes to commit messages, without
-changing the commit. To discern these notes from the message stored
-in the commit object, the notes are indented like the message, after
-an unindented line saying "Notes:".
-
-To disable commit notes, you have to set the config variable
-core.notesRef to the empty string. Alternatively, you can set it
-to a different ref, something like "refs/notes/bugzilla". This setting
-can be overridden by the environment variable "GIT_NOTES_REF".
-
-
-SUBCOMMANDS
------------
-
-edit::
- Edit the notes for a given commit (defaults to HEAD).
-
-show::
- Show the notes for a given commit (defaults to HEAD).
-
-
-Author
-------
-Written by Johannes Schindelin <johannes.schindelin@gmx.de>
-
-Documentation
--------------
-Documentation by Johannes Schindelin
-
-GIT
----
-Part of the gitlink:git[7] suite
SCRIPT_SH += git-merge-one-file.sh
SCRIPT_SH += git-merge-resolve.sh
SCRIPT_SH += git-mergetool.sh
-SCRIPT_SH += git-notes.sh
SCRIPT_SH += git-parse-remote.sh
SCRIPT_SH += git-pull.sh
SCRIPT_SH += git-quiltimport.sh
LIB_H += log-tree.h
LIB_H += mailmap.h
LIB_H += merge-recursive.h
-LIB_H += notes.h
LIB_H += object.h
LIB_H += pack.h
LIB_H += pack-refs.h
LIB_OBJS += merge-file.o
LIB_OBJS += merge-recursive.o
LIB_OBJS += name-hash.o
-LIB_OBJS += notes.o
LIB_OBJS += object.o
LIB_OBJS += pack-check.o
LIB_OBJS += pack-refs.o
#define GITATTRIBUTES_FILE ".gitattributes"
#define INFOATTRIBUTES_FILE "info/attributes"
#define ATTRIBUTE_MACRO_PREFIX "[attr]"
-#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
-#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
extern int is_bare_repository_cfg;
extern int is_bare_repository(void);
extern enum branch_track git_branch_track;
extern enum rebase_setup_type autorebase;
-extern char *notes_ref_name;
#define GIT_REPO_VERSION 0
extern int repository_format_version;
git-mktree plumbingmanipulators
git-mv mainporcelain common
git-name-rev plumbinginterrogators
-git-notes mainporcelain
git-pack-objects plumbingmanipulators
git-pack-redundant plumbinginterrogators
git-pack-refs ancillarymanipulators
#include "utf8.h"
#include "diff.h"
#include "revision.h"
-#include "notes.h"
int save_commit_buffer = 1;
return 0;
}
- if (!strcmp(var, "core.notesref")) {
- notes_ref_name = xstrdup(value);
- return 0;
- }
-
if (!strcmp(var, "core.pager"))
return git_config_string(&pager_program, var, value);
/* Parallel index stat data preload? */
int core_preload_index = 0;
-char *notes_ref_name;
/* This is set by setup_git_dir_gently() and/or git_default_config() */
char *git_work_tree_cfg;
+++ /dev/null
-#!/bin/sh
-
-USAGE="(edit | show) [commit]"
-. git-sh-setup
-
-test -n "$3" && usage
-
-test -z "$1" && usage
-ACTION="$1"; shift
-
-test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="$(git config core.notesref)"
-test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="refs/notes/commits"
-
-COMMIT=$(git rev-parse --verify --default HEAD "$@") ||
-die "Invalid commit: $@"
-
-MESSAGE="$GIT_DIR"/new-notes-$COMMIT
-trap '
- test -f "$MESSAGE" && rm "$MESSAGE"
-' 0
-
-case "$ACTION" in
-edit)
- GIT_NOTES_REF= git log -1 $COMMIT | sed "s/^/#/" > "$MESSAGE"
-
- GIT_INDEX_FILE="$MESSAGE".idx
- export GIT_INDEX_FILE
-
- CURRENT_HEAD=$(git show-ref "$GIT_NOTES_REF" | cut -f 1 -d ' ')
- if [ -z "$CURRENT_HEAD" ]; then
- PARENT=
- else
- PARENT="-p $CURRENT_HEAD"
- git read-tree "$GIT_NOTES_REF" || die "Could not read index"
- git cat-file blob :$COMMIT >> "$MESSAGE" 2> /dev/null
- fi
-
- ${VISUAL:-${EDITOR:-vi}} "$MESSAGE"
-
- grep -v ^# < "$MESSAGE" | git stripspace > "$MESSAGE".processed
- mv "$MESSAGE".processed "$MESSAGE"
- if [ -s "$MESSAGE" ]; then
- BLOB=$(git hash-object -w "$MESSAGE") ||
- die "Could not write into object database"
- git update-index --add --cacheinfo 0644 $BLOB $COMMIT ||
- die "Could not write index"
- else
- test -z "$CURRENT_HEAD" &&
- die "Will not initialise with empty tree"
- git update-index --force-remove $COMMIT ||
- die "Could not update index"
- fi
-
- TREE=$(git write-tree) || die "Could not write tree"
- NEW_HEAD=$(echo Annotate $COMMIT | git commit-tree $TREE $PARENT) ||
- die "Could not annotate"
- git update-ref -m "Annotate $COMMIT" \
- "$GIT_NOTES_REF" $NEW_HEAD $CURRENT_HEAD
-;;
-show)
- git show "$GIT_NOTES_REF":$COMMIT
-;;
-*)
- usage
-esac
+++ /dev/null
-#include "cache.h"
-#include "commit.h"
-#include "notes.h"
-#include "refs.h"
-#include "utf8.h"
-#include "strbuf.h"
-#include "tree-walk.h"
-
-struct entry {
- unsigned char commit_sha1[20];
- unsigned char notes_sha1[20];
-};
-
-struct hash_map {
- struct entry *entries;
- off_t count, size;
-};
-
-static int initialized;
-static struct hash_map hash_map;
-
-static int hash_index(struct hash_map *map, const unsigned char *sha1)
-{
- int i = ((*(unsigned int *)sha1) % map->size);
-
- for (;;) {
- unsigned char *current = map->entries[i].commit_sha1;
-
- if (!hashcmp(sha1, current))
- return i;
-
- if (is_null_sha1(current))
- return -1 - i;
-
- if (++i == map->size)
- i = 0;
- }
-}
-
-static void add_entry(const unsigned char *commit_sha1,
- const unsigned char *notes_sha1)
-{
- int index;
-
- if (hash_map.count + 1 > hash_map.size >> 1) {
- int i, old_size = hash_map.size;
- struct entry *old = hash_map.entries;
-
- hash_map.size = old_size ? old_size << 1 : 64;
- hash_map.entries = (struct entry *)
- xcalloc(sizeof(struct entry), hash_map.size);
-
- for (i = 0; i < old_size; i++)
- if (!is_null_sha1(old[i].commit_sha1)) {
- index = -1 - hash_index(&hash_map,
- old[i].commit_sha1);
- memcpy(hash_map.entries + index, old + i,
- sizeof(struct entry));
- }
- free(old);
- }
-
- index = hash_index(&hash_map, commit_sha1);
- if (index < 0) {
- index = -1 - index;
- hash_map.count++;
- }
-
- hashcpy(hash_map.entries[index].commit_sha1, commit_sha1);
- hashcpy(hash_map.entries[index].notes_sha1, notes_sha1);
-}
-
-static void initialize_hash_map(const char *notes_ref_name)
-{
- unsigned char sha1[20], commit_sha1[20];
- unsigned mode;
- struct tree_desc desc;
- struct name_entry entry;
- void *buf;
-
- if (!notes_ref_name || read_ref(notes_ref_name, commit_sha1) ||
- get_tree_entry(commit_sha1, "", sha1, &mode))
- return;
-
- buf = fill_tree_descriptor(&desc, sha1);
- if (!buf)
- die("Could not read %s for notes-index", sha1_to_hex(sha1));
-
- while (tree_entry(&desc, &entry))
- if (!get_sha1(entry.path, commit_sha1))
- add_entry(commit_sha1, entry.sha1);
- free(buf);
-}
-
-static unsigned char *lookup_notes(const unsigned char *commit_sha1)
-{
- int index;
-
- if (!hash_map.size)
- return NULL;
-
- index = hash_index(&hash_map, commit_sha1);
- if (index < 0)
- return NULL;
- return hash_map.entries[index].notes_sha1;
-}
-
-void get_commit_notes(const struct commit *commit, struct strbuf *sb,
- const char *output_encoding)
-{
- static const char *utf8 = "utf-8";
- unsigned char *sha1;
- char *msg, *msg_p;
- unsigned long linelen, msglen;
- enum object_type type;
-
- if (!initialized) {
- const char *env = getenv(GIT_NOTES_REF_ENVIRONMENT);
- if (env)
- notes_ref_name = getenv(GIT_NOTES_REF_ENVIRONMENT);
- else if (!notes_ref_name)
- notes_ref_name = GIT_NOTES_DEFAULT_REF;
- initialize_hash_map(notes_ref_name);
- initialized = 1;
- }
-
- sha1 = lookup_notes(commit->object.sha1);
- if (!sha1)
- return;
-
- if (!(msg = read_sha1_file(sha1, &type, &msglen)) || !msglen ||
- type != OBJ_BLOB)
- return;
-
- if (output_encoding && *output_encoding &&
- strcmp(utf8, output_encoding)) {
- char *reencoded = reencode_string(msg, output_encoding, utf8);
- if (reencoded) {
- free(msg);
- msg = reencoded;
- msglen = strlen(msg);
- }
- }
-
- /* we will end the annotation by a newline anyway */
- if (msglen && msg[msglen - 1] == '\n')
- msglen--;
-
- strbuf_addstr(sb, "\nNotes:\n");
-
- for (msg_p = msg; msg_p < msg + msglen; msg_p += linelen + 1) {
- linelen = strchrnul(msg_p, '\n') - msg_p;
-
- strbuf_addstr(sb, " ");
- strbuf_add(sb, msg_p, linelen);
- strbuf_addch(sb, '\n');
- }
-
- free(msg);
-}
+++ /dev/null
-#ifndef NOTES_H
-#define NOTES_H
-
-void get_commit_notes(const struct commit *commit, struct strbuf *sb,
- const char *output_encoding);
-
-#endif
#include "string-list.h"
#include "mailmap.h"
#include "log-tree.h"
-#include "notes.h"
#include "color.h"
static char *user_format;
*/
if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
strbuf_addch(sb, '\n');
-
- if (fmt != CMIT_FMT_ONELINE)
- get_commit_notes(commit, sb, encoding);
-
free(reencoded);
}
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2007 Johannes E. Schindelin
-#
-
-test_description='Test commit notes'
-
-. ./test-lib.sh
-
-cat > fake_editor.sh << \EOF
-echo "$MSG" > "$1"
-echo "$MSG" >& 2
-EOF
-chmod a+x fake_editor.sh
-VISUAL=./fake_editor.sh
-export VISUAL
-
-test_expect_success 'cannot annotate non-existing HEAD' '
- ! MSG=3 git notes edit
-'
-
-test_expect_success setup '
- : > a1 &&
- git add a1 &&
- test_tick &&
- git commit -m 1st &&
- : > a2 &&
- git add a2 &&
- test_tick &&
- git commit -m 2nd
-'
-
-test_expect_success 'need valid notes ref' '
- ! MSG=1 GIT_NOTES_REF='/' git notes edit &&
- ! MSG=2 GIT_NOTES_REF='/' git notes show
-'
-
-test_expect_success 'create notes' '
- git config core.notesRef refs/notes/commits &&
- MSG=b1 git notes edit &&
- test ! -f .git/new-notes &&
- test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
- test b1 = $(git notes show) &&
- git show HEAD^ &&
- ! git notes show HEAD^
-'
-
-cat > expect << EOF
-commit 268048bfb8a1fb38e703baceb8ab235421bf80c5
-Author: A U Thor <author@example.com>
-Date: Thu Apr 7 15:14:13 2005 -0700
-
- 2nd
-
-Notes:
- b1
-EOF
-
-test_expect_success 'show notes' '
- ! (git cat-file commit HEAD | grep b1) &&
- git log -1 > output &&
- test_cmp expect output
-'
-test_expect_success 'create multi-line notes (setup)' '
- : > a3 &&
- git add a3 &&
- test_tick &&
- git commit -m 3rd &&
- MSG="b3
-c3c3c3c3
-d3d3d3" git notes edit
-'
-
-cat > expect-multiline << EOF
-commit 1584215f1d29c65e99c6c6848626553fdd07fd75
-Author: A U Thor <author@example.com>
-Date: Thu Apr 7 15:15:13 2005 -0700
-
- 3rd
-
-Notes:
- b3
- c3c3c3c3
- d3d3d3
-EOF
-
-printf "\n" >> expect-multiline
-cat expect >> expect-multiline
-
-test_expect_success 'show multi-line notes' '
- git log -2 > output &&
- test_cmp expect-multiline output
-'
-
-test_done
+++ /dev/null
-#!/bin/sh
-#
-# Copyright (c) 2007 Johannes E. Schindelin
-#
-
-test_description='Test commit notes index (expensive!)'
-
-. ./test-lib.sh
-
-test -z "$GIT_NOTES_TIMING_TESTS" && {
- say Skipping timing tests
- test_done
- exit
-}
-
-create_repo () {
- number_of_commits=$1
- nr=0
- parent=
- test -d .git || {
- git init &&
- tree=$(git write-tree) &&
- while [ $nr -lt $number_of_commits ]; do
- test_tick &&
- commit=$(echo $nr | git commit-tree $tree $parent) ||
- return
- parent="-p $commit"
- nr=$(($nr+1))
- done &&
- git update-ref refs/heads/master $commit &&
- {
- export GIT_INDEX_FILE=.git/temp;
- git rev-list HEAD | cat -n | sed "s/^[ ][ ]*/ /g" |
- while read nr sha1; do
- blob=$(echo note $nr | git hash-object -w --stdin) &&
- echo $sha1 | sed "s/^/0644 $blob 0 /"
- done | git update-index --index-info &&
- tree=$(git write-tree) &&
- test_tick &&
- commit=$(echo notes | git commit-tree $tree) &&
- git update-ref refs/notes/commits $commit
- } &&
- git config core.notesRef refs/notes/commits
- }
-}
-
-test_notes () {
- count=$1 &&
- git config core.notesRef refs/notes/commits &&
- git log | grep "^ " > output &&
- i=1 &&
- while [ $i -le $count ]; do
- echo " $(($count-$i))" &&
- echo " note $i" &&
- i=$(($i+1));
- done > expect &&
- git diff expect output
-}
-
-cat > time_notes << \EOF
- mode=$1
- i=1
- while [ $i -lt $2 ]; do
- case $1 in
- no-notes)
- export GIT_NOTES_REF=non-existing
- ;;
- notes)
- unset GIT_NOTES_REF
- ;;
- esac
- git log >/dev/null
- i=$(($i+1))
- done
-EOF
-
-time_notes () {
- for mode in no-notes notes
- do
- echo $mode
- /usr/bin/time sh ../time_notes $mode $1
- done
-}
-
-for count in 10 100 1000 10000; do
-
- mkdir $count
- (cd $count;
-
- test_expect_success "setup $count" "create_repo $count"
-
- test_expect_success 'notes work' "test_notes $count"
-
- test_expect_success 'notes timing' "time_notes 100"
- )
-done
-
-test_done