#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target( \
    "sse,sse2,sse3,ssse3,sse4,sse4.1,sse4.2,popcnt,abm,mmx,avx,tune=native")
using namespace std;
const int MAXBUF = 1 << 23;
char B[MAXBUF], *Si = B, *Ti = B;
inline char getc() {
  if (Si == Ti) Ti = (Si = B) + fread(B, 1, MAXBUF, stdin);
  if (Si == Ti)
    return 0;
  else
    return *Si++;
}
template <class T>
inline void read(T &a) {
  static char c;
  static int fh;
  while (((c = getc()) < '0' || c > '9') && c != '-')
    ;
  if (c == '-')
    fh = -1, a = 0;
  else
    fh = 1, a = c - '0';
  while ((c = getc()) <= '9' && c >= '0') a = (a << 3) + (a << 1) + c - '0';
  if (fh == -1) a = -a;
}
char Buff[MAXBUF], *sti = Buff;
template <class T>
inline void write(T a) {
  if (a == 0) {
    *sti++ = '0';
    return;
  }
  if (a < 0) *sti++ = '-', a = -a;
  static char c[20];
  static int c0;
  c0 = 0;
  while (a) c[c0++] = a % 10 + '0', a /= 10;
  while (c0--) *sti++ = c[c0];
}
struct r_base {
  int pos, val;
} t1[31];
struct r_dsu {
  int a, b, prk, pg;
} t2[200005];
struct edge {
  int a, b, c, l, r;
} e[400005];
unordered_map<int, int> mp[200005];
int fa[200005], rnk[200005], g[200005];
int bas[31], c1 = 0, c2 = 0, cnt = 0, n, m;
int f[200005][2];
vector<int> vec[600005];
void add(int pos, int l, int r, int lp, int rp, int id) {
  if (l == lp && r == rp) {
    vec[pos].push_back(id);
    return;
  }
  int mid = (l + r) >> 1;
  if (rp <= mid) add((pos << 1), l, mid, lp, rp, id);
  if (lp > mid) add((pos << 1 | 1), mid + 1, r, lp, rp, id);
  if (lp <= mid && rp > mid) {
    add((pos << 1), l, mid, lp, mid, id);
    add((pos << 1 | 1), mid + 1, r, mid + 1, rp, id);
  }
}
inline int getf(int a) {
  while (a ^ fa[a]) a = fa[a];
  return a;
}
inline int get(int a) {
  int x = 0;
  while (a ^ fa[a]) x ^= g[a], a = fa[a];
  return x;
}
inline void add(int a, int b) {
  t1[++c1].pos = a;
  t1[c1].val = b;
  bas[a] = b;
}
inline void roll_bas(int o) {
  while (c1 > o) {
    bas[t1[c1].pos] = 0;
    c1--;
  }
}
inline void roll_dsu(int o) {
  while (c2 > o) {
    rnk[t2[c2].b] = t2[c2].prk;
    g[t2[c2].a] = t2[c2].pg;
    fa[t2[c2].a] = t2[c2].a;
    c2--;
  }
}
inline void query(int a, int b) {
  int ans = get(a) ^ get(b), i;
  for (i = 29; i >= 0; i--) {
    if ((ans ^ bas[i]) < ans) ans ^= bas[i];
  }
  write(ans), *sti++ = '\n';
}
inline void merge(int id) {
  int a = e[id].a, b = e[id].b, c = e[id].c;
  int pa = getf(a), push_back = getf(b), i;
  if (pa ^ push_back) {
    if (rnk[pa] > rnk[push_back]) swap(pa, push_back);
    t2[++c2].a = pa;
    t2[c2].b = push_back;
    t2[c2].prk = rnk[push_back];
    t2[c2].pg = g[pa];
    fa[pa] = push_back;
    g[pa] = get(a) ^ get(b) ^ c;
    if (rnk[pa] == rnk[push_back]) rnk[push_back]++;
    return;
  }
  int x = get(a) ^ get(b) ^ c;
  for (i = 29; i >= 0; i--) {
    if (x & (1 << i)) {
      if (!bas[i]) {
        add(i, x);
        break;
      } else {
        x ^= bas[i];
      }
    }
  }
}
void solve(int pos, int l, int r) {
  int k1 = c1, k2 = c2, i, sz = vec[pos].size();
  for (i = 0; i < sz; i++) merge(vec[pos][i]);
  int mid = (l + r) >> 1;
  if (l == r) {
    query(f[l][0], f[l][1]);
  }
  if (l ^ r) {
    solve((pos << 1), l, mid);
    solve((pos << 1 | 1), mid + 1, r);
  }
  roll_bas(k1);
  roll_dsu(k2);
}
int main() {
  int i, j, opt, x, y, q;
  read(n);
  read(m);
  for (i = 1; i <= m; i++) {
    read(e[i].a);
    read(e[i].b);
    read(e[i].c);
    e[i].l = cnt + 1;
    e[i].r = -1;
    mp[e[i].a][e[i].b] = i;
  }
  read(q);
  while (q--) {
    read(opt);
    read(x);
    read(y);
    if (opt == 1) {
      read(e[++m].c);
      e[m].a = x;
      e[m].b = y;
      e[m].l = cnt + 1;
      e[m].r = -1;
      mp[e[m].a][e[m].b] = m;
      continue;
    }
    if (opt == 2) e[mp[x][y]].r = cnt;
    if (opt == 3) f[++cnt][0] = x, f[cnt][1] = y;
  }
  for (i = 1; i <= m; i++) {
    if (e[i].r == -1) e[i].r = cnt;
    if (e[i].l <= e[i].r) add(1, 1, cnt, e[i].l, e[i].r, i);
  }
  for (i = 1; i <= n; i++) fa[i] = i;
  solve(1, 1, cnt);
  fwrite(Buff, 1, sti - Buff, stdout);
  return 0;
}
